// PRIVATE METHODS ////////////////////////////////////////////////// #region Methods private static void AddOrUpdateApiTypeConfiguration <TConfiguration, TMutableFactory, TMutable>(IDictionary <Type, ApiTypeConfiguration> dictionary, ApiTypeConfiguration apiTypeConfiguration, Type apiTypeConfigurationOpenGenericType, ApiPrecedenceLevel apiPrecedenceLevel, ApiPrecedenceStack apiPrecedenceStack) where TConfiguration : ApiTypeConfiguration where TMutableFactory : ApiMutableFactory <ApiMutableSchema, TMutable> { Contract.Requires(dictionary != null); Contract.Requires(apiTypeConfiguration != null); Contract.Requires(apiTypeConfigurationOpenGenericType != null); Contract.Requires(apiPrecedenceStack != null); var apiConfigurationIncoming = (TConfiguration)apiTypeConfiguration; var apiObjectFactoryIncoming = (TMutableFactory)apiConfigurationIncoming.ApiMutableFactory; var clrType = apiTypeConfiguration.ClrType; if (dictionary.TryGetValue(clrType, out var apiConfiguration)) { // Update the existing API configuration by merging the incoming derived API configuration. var apiConfigurationExisting = (TConfiguration)apiConfiguration; var apiObjectFactoryExisting = (TMutableFactory)apiConfigurationExisting.ApiMutableFactory; apiObjectFactoryExisting.Merge(apiObjectFactoryIncoming); return; } // Create a new API configuration from the incoming derived API configuration. var apiConfigurationNew = ApiTypeConfigurationFactory.CreateApiTypeConfiguration <TConfiguration, TMutableFactory, TMutable>(clrType, apiTypeConfigurationOpenGenericType, apiPrecedenceStack, apiObjectFactoryIncoming); dictionary.Add(clrType, apiConfigurationNew); ApiFrameworkLog.Trace($"Added {typeof(TConfiguration).Name} [ClrType={apiConfigurationNew.ClrType.Name}] at {apiPrecedenceLevel} Level".Indent(IndentConstants.ApiMutableSchemaModifier)); }
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); }
IApiObjectTypeBuilder IApiObjectTypeBuilder.ApiRelationship(string clrPropertyName, Type clrPropertyType) { Contract.Requires(clrPropertyName.SafeHasContent()); Contract.Requires(clrPropertyType != null); var apiConfigurationLevel = this.ApiPrecedenceStack.CurrentLevel; this.ApiMutableObjectTypeFactory.AddModifier(apiConfigurationLevel, x => { // Preserve the order in which API relationships are added. if (x.ClrRelationshipPropertyIndexDictionary.TryGetValue(clrPropertyName, out var clrRelationshipPropertyIndex)) { return; } var clrRelationshipProperty = new ClrRelationshipProperty(clrPropertyName, clrPropertyType); clrRelationshipPropertyIndex = x.ClrRelationshipPropertyIndexDictionary.Count; ApiFrameworkLog.Trace($"Added {clrRelationshipProperty} at {apiConfigurationLevel} Level".Indent(IndentConstants.ApiMutableObjectTypeModifier)); x.ClrRelationshipPropertyCollection.Add(clrRelationshipProperty); x.ClrRelationshipPropertyIndexDictionary.Add(clrPropertyName, clrRelationshipPropertyIndex); }, CallerTypeName); return(this); }
// PUBLIC METHODS /////////////////////////////////////////////////// #region IApiSchemaBuilder Implementation public IApiSchemaBuilder Exclude(Type clrType) { Contract.Requires(clrType != null); var apiConfigurationLevel = this.ApiPrecedenceStack.CurrentLevel; var apiTypeKind = clrType.GetApiTypeKind(); switch (apiTypeKind) { case ApiTypeKind.Object: { this.ApiMutableSchemaFactory.AddModifier(apiConfigurationLevel, x => { ApiFrameworkLog.Trace( $"Excluded {nameof(Schema.Internal.ApiObjectType)} [{nameof(Schema.Internal.ApiObjectType.ClrType)}={clrType.Name}] at {apiConfigurationLevel} Level".Indent( IndentConstants.ApiMutableSchemaModifier)); x.AddClrExcludedObjectType(clrType); }, CallerTypeName); break; } case ApiTypeKind.Scalar: { this.ApiMutableSchemaFactory.AddModifier(apiConfigurationLevel, x => { ApiFrameworkLog.Trace( $"Excluded {nameof(Schema.Internal.ApiScalarType)} [{nameof(Schema.Internal.ApiScalarType.ClrType)}={clrType.Name}] at {apiConfigurationLevel} Level".Indent( IndentConstants.ApiMutableSchemaModifier)); x.AddClrExcludedScalarType(clrType); }, CallerTypeName); break; } case ApiTypeKind.Enumeration: { this.ApiMutableSchemaFactory.AddModifier(apiConfigurationLevel, x => { ApiFrameworkLog.Trace( $"Excluded {nameof(Schema.Internal.ApiEnumerationType)} [{nameof(Schema.Internal.ApiEnumerationType.ClrType)}={clrType.Name}] at {apiConfigurationLevel} Level".Indent( IndentConstants.ApiMutableSchemaModifier)); x.AddClrExcludedEnumerationType(clrType); }, CallerTypeName); break; } } return(this); }
public IApiEnumerationValue Create(ApiMutableSchema apiMutableSchema) { Contract.Requires(apiMutableSchema != null); var apiMutableEnumerationValue = this.ApiMutableEnumerationValueFactory.Create(apiMutableSchema); var apiEnumerationValue = CreateApiEnumerationValue(apiMutableEnumerationValue); ApiFrameworkLog.Debug($"Created {apiEnumerationValue}".Indent(IndentConstants.ApiEnumerationValue)); return(apiEnumerationValue); }
internal override IApiType CreateApiType(ApiMutableType apiMutableType, ApiSchemaProxy apiSchemaProxy) { Contract.Requires(apiMutableType != null); Contract.Requires(apiSchemaProxy != null); var apiMutableScalarType = (ApiMutableScalarType)apiMutableType; var apiScalarType = CreateApiScalarType(apiMutableScalarType); ApiFrameworkLog.Debug($"Created {apiScalarType}".Indent(IndentConstants.ApiScalarType)); return(apiScalarType); }
public IApiCollectionType Create(ApiMutableSchema apiMutableSchema, ApiSchemaProxy apiSchemaProxy) { Contract.Requires(apiMutableSchema != null); Contract.Requires(apiSchemaProxy != null); var apiMutableCollectionType = this.CreateApiMutableType(apiMutableSchema); var apiCollectionType = (IApiCollectionType)this.CreateApiType(apiMutableCollectionType, apiSchemaProxy); ApiFrameworkLog.Debug($"Created {apiCollectionType}".Indent(IndentConstants.ApiCollectionType)); return(apiCollectionType); }
public IApiProperty CreateApiProperty(ApiMutableSchema apiMutableSchema, ApiMutableObjectType apiMutableObjectType, ApiSchemaProxy apiSchemaProxy) { Contract.Requires(apiMutableSchema != null); Contract.Requires(apiMutableObjectType != null); Contract.Requires(apiSchemaProxy != null); var apiMutableProperty = this.ApiMutablePropertyFactory.Create(apiMutableSchema); var apiProperty = CreateApiProperty(apiMutableObjectType, apiMutableProperty, apiSchemaProxy); ApiFrameworkLog.Debug($"Created {apiProperty}".Indent(IndentConstants.ApiProperty)); return(apiProperty); }
private static TApiConfiguration GetOrAddApiConfiguration <TApiConfiguration>(IDictionary <Type, ApiTypeConfiguration> dictionary, Type clrType, Type apiConfigurationOpenGenericType, ApiPrecedenceLevel apiPrecedenceLevel, ApiPrecedenceStack apiPrecedenceStack) where TApiConfiguration : ApiTypeConfiguration { Contract.Requires(dictionary != null); Contract.Requires(clrType != null); Contract.Requires(apiConfigurationOpenGenericType != null); Contract.Requires(apiPrecedenceStack != null); if (dictionary.TryGetValue(clrType, out var apiConfiguration)) { var apiConfigurationExisting = (TApiConfiguration)apiConfiguration; return(apiConfigurationExisting); } var apiConfigurationNew = ApiTypeConfigurationFactory.CreateApiTypeConfiguration <TApiConfiguration>(clrType, apiConfigurationOpenGenericType, apiPrecedenceStack); dictionary.Add(clrType, apiConfigurationNew); var apiTypeKind = apiConfigurationNew.ApiTypeKind; switch (apiTypeKind) { case ApiTypeKind.Enumeration: { ApiFrameworkLog.Trace($"Added {nameof(ApiEnumerationType)} [{nameof(ApiEnumerationType.ClrType)}={clrType.Name}] at {apiPrecedenceLevel} Level".Indent(IndentConstants.ApiMutableSchemaModifier)); break; } case ApiTypeKind.Object: { ApiFrameworkLog.Trace($"Added {nameof(ApiObjectType)} [{nameof(ApiObjectType.ClrType)}={clrType.Name}] at {apiPrecedenceLevel} Level".Indent(IndentConstants.ApiMutableSchemaModifier)); break; } case ApiTypeKind.Scalar: { ApiFrameworkLog.Trace($"Added {nameof(ApiScalarType)} [{nameof(ApiScalarType.ClrType)}={clrType.Name}] at {apiPrecedenceLevel} Level".Indent(IndentConstants.ApiMutableSchemaModifier)); break; } default: throw new ArgumentOutOfRangeException(); } return(apiConfigurationNew); }
public IApiSchema Create(ApiSchemaFactorySettings apiSchemaFactorySettings) { ApiFrameworkLog.Debug($"Creating {nameof(ApiSchema)}".Indent(IndentConstants.ApiSchema)); var apiMutableSchema = this.ApiMutableSchemaFactory.Create(apiSchemaFactorySettings); var apiSchema = CreateApiSchema(apiMutableSchema, this.ApiPrecedenceStack); var createdApiSchema = apiSchema.ToTreeString(); ApiFrameworkLog.Information($"Created {nameof(ApiSchema)}" + "\n" + "{CreatedApiSchema}".Indent(IndentConstants.ApiSchema), createdApiSchema); return(apiSchema); }
public IApiSchemaBuilder HasName(string apiName) { Contract.Requires(apiName.SafeHasContent()); var apiConfigurationLevel = this.ApiPrecedenceStack.CurrentLevel; this.ApiMutableSchemaFactory.AddModifier(apiConfigurationLevel, x => { ApiFrameworkLog.Trace($"Modified {nameof(x.ApiName)} '{x.ApiName}' => '{apiName}' at {apiConfigurationLevel} Level".Indent(IndentConstants.ApiMutableSchemaModifier)); x.ApiName = apiName; }, CallerTypeName); return(this); }
public IApiPropertyBuilder IsRequired() { var apiConfigurationLevel = this.ApiPrecedenceStack.CurrentLevel; this.ApiMutablePropertyFactory.AddModifier(apiConfigurationLevel, x => { var apiTypeModifiers = x.ApiTypeModifiers; x.ApiTypeModifiers |= ApiTypeModifiers.Required; ApiFrameworkLog.Trace($"Modified {nameof(x.ApiTypeModifiers)} '{apiTypeModifiers}' => '{x.ApiTypeModifiers}' at {apiConfigurationLevel} Level".Indent(IndentConstants.ApiMutablePropertyModifier)); }, CallerTypeName); return(this); }
public IApiPropertyBuilder HasDescription(string apiDescription) { Contract.Requires(apiDescription.SafeHasContent()); var apiConfigurationLevel = this.ApiPrecedenceStack.CurrentLevel; this.ApiMutablePropertyFactory.AddModifier(apiConfigurationLevel, x => { ApiFrameworkLog.Trace($"Modified {nameof(x.ApiDescription)} '{x.ApiDescription}' => '{apiDescription}' at {apiConfigurationLevel} Level".Indent(IndentConstants.ApiMutablePropertyModifier)); x.ApiDescription = apiDescription; }, CallerTypeName); return(this); }
// PUBLIC METHODS /////////////////////////////////////////////////// #region IApiObjectTypeBuilder Implementation IApiObjectTypeBuilder IApiObjectTypeBuilder.Exclude(string clrPropertyName) { Contract.Requires(clrPropertyName.SafeHasContent()); var apiConfigurationLevel = this.ApiPrecedenceStack.CurrentLevel; this.ApiMutableObjectTypeFactory.AddModifier(apiConfigurationLevel, x => { ApiFrameworkLog.Trace($"Excluded {nameof(ApiProperty)} [{nameof(ApiProperty.ClrName)}={clrPropertyName}] at {apiConfigurationLevel} Level".Indent(IndentConstants.ApiMutableObjectTypeModifier)); x.ClrExcludedPropertyNames.Add(clrPropertyName); }, CallerTypeName); return(this); }
private static IEnumerable <IApiObjectType> CreateApiObjectTypes(ApiMutableSchema apiMutableSchema, ApiSchemaProxy apiSchemaProxy) { Contract.Requires(apiMutableSchema != null); Contract.Requires(apiSchemaProxy != null); ApiFrameworkLog.Debug($"Creating {nameof(ApiObjectType)}s".Indent(IndentConstants.ApiObjectTypes)); var apiObjectTypeConfigurations = apiMutableSchema.ApiObjectTypeConfigurationDictionary .Values .ToList(); var clrExcludedObjectTypes = apiMutableSchema.ClrExcludedObjectTypes; var apiObjectTypes = CreateApiTypes <IApiObjectType>(apiMutableSchema, apiSchemaProxy, apiObjectTypeConfigurations, clrExcludedObjectTypes); ApiFrameworkLog.Debug($"Created {nameof(ApiObjectType)}s".Indent(IndentConstants.ApiObjectTypes)); return(apiObjectTypes); }
private static IEnumerable <IApiEnumerationType> CreateApiEnumerationTypes(ApiMutableSchema apiMutableSchema, ApiPrecedenceStack apiPrecedenceStack, ApiSchemaProxy apiSchemaProxy) { Contract.Requires(apiMutableSchema != null); Contract.Requires(apiPrecedenceStack != null); ApiFrameworkLog.Debug($"Creating {nameof(ApiEnumerationType)}s".Indent(IndentConstants.ApiEnumerationTypes)); RemoveUnusedApiEnumerationTypes(apiMutableSchema); AddMissingApiEnumerationTypes(apiMutableSchema, apiPrecedenceStack); var apiEnumerationTypeConfigurations = apiMutableSchema.ApiEnumerationTypeConfigurationDictionary .Values .ToList(); var clrExcludedEnumerationTypes = apiMutableSchema.ClrExcludedEnumerationTypes; var apiEnumerationTypes = CreateApiTypes <IApiEnumerationType>(apiMutableSchema, apiSchemaProxy, apiEnumerationTypeConfigurations, clrExcludedEnumerationTypes); ApiFrameworkLog.Debug($"Created {nameof(ApiEnumerationType)}s".Indent(IndentConstants.ApiEnumerationTypes)); return(apiEnumerationTypes); }
IApiObjectTypeBuilder IApiObjectTypeBuilder.ApiIdentity(string clrPropertyName, Type clrPropertyType) { Contract.Requires(clrPropertyName.SafeHasContent()); Contract.Requires(clrPropertyType != null); var apiConfigurationLevel = this.ApiPrecedenceStack.CurrentLevel; this.ApiMutableObjectTypeFactory.AddModifier(apiConfigurationLevel, x => { // This API object type is an API resource type because it has identity, register with the mutable API schema object. var clrObjectType = x.ClrObjectType; var apiMutableSchema = x.ApiMutableSchema; apiMutableSchema.AddClrResourceType(clrObjectType); var clrIdentityProperty = new ClrIdentityProperty(clrPropertyName, clrPropertyType); ApiFrameworkLog.Trace($"Set {clrIdentityProperty} at {apiConfigurationLevel} Level".Indent(IndentConstants.ApiMutableObjectTypeModifier)); x.ClrIdentityProperty = clrIdentityProperty; }, CallerTypeName); return(this); }
private static ApiEnumerationValueConfiguration GetOrAddApiEnumerationValueConfiguration(ApiMutableEnumerationType apiMutableEnumerationType, string clrName, int clrOrdinal, ApiPrecedenceLevel apiPrecedenceLevel, ApiPrecedenceStack apiPrecedenceStack) { Contract.Requires(apiMutableEnumerationType != null); Contract.Requires(clrName.SafeHasContent()); Contract.Requires(apiPrecedenceStack != null); if (apiMutableEnumerationType.ApiEnumerationValueConfigurations.TryGetValue(clrOrdinal, out var apiEnumerationValueConfigurationExisting)) { return(apiEnumerationValueConfigurationExisting); } var apiEnumerationValueConfigurationNew = new ApiEnumerationValueConfiguration(clrName, clrOrdinal, apiPrecedenceStack); apiMutableEnumerationType.ApiEnumerationValueConfigurations.Add(clrOrdinal, apiEnumerationValueConfigurationNew); ApiFrameworkLog.Trace($"Added {nameof(ApiEnumerationValue)} [{nameof(ApiEnumerationValue.ClrName)}={clrName}] at {apiPrecedenceLevel} Level".Indent(IndentConstants.ApiMutableEnumerationTypeModifier)); return(apiEnumerationValueConfigurationNew); }
// 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); }