// INTERNAL METHODS /////////////////////////////////////////////////
        #region ApiTypeConfiguration Overrides
        internal override ApiMutableType CreateApiMutableType(ApiMutableSchema apiMutableSchema)
        {
            Contract.Requires(apiMutableSchema != null);

            var apiMutableEnumerationType = this.ApiMutableEnumerationTypeFactory.Create(apiMutableSchema);

            return(apiMutableEnumerationType);
        }
        private static void RemoveUnusedApiScalarTypes(ApiMutableSchema apiMutableSchema)
        {
            Contract.Requires(apiMutableSchema != null);

            var clrExplicitScalarTypes = apiMutableSchema.ApiScalarTypeConfigurationDictionary
                                         .Keys
                                         .ToList();

            var clrUnusedScalarTypes = new HashSet <Type>(clrExplicitScalarTypes);

            clrUnusedScalarTypes.ExceptWith(apiMutableSchema.ClrImplicitScalarTypes);

            foreach (var clrUnusedScalarType in clrUnusedScalarTypes)
            {
                apiMutableSchema.ApiScalarTypeConfigurationDictionary
                .Remove(clrUnusedScalarType);
            }
        }
        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 void AddMissingApiScalarTypes(ApiMutableSchema apiMutableSchema, ApiPrecedenceStack apiPrecedenceStack)
        {
            Contract.Requires(apiMutableSchema != null);
            Contract.Requires(apiPrecedenceStack != null);

            var clrExplicitScalarTypes = apiMutableSchema.ApiScalarTypeConfigurationDictionary
                                         .Keys
                                         .ToList();

            var clrMissingScalarTypes = new HashSet <Type>(apiMutableSchema.ClrImplicitScalarTypes);

            clrMissingScalarTypes.ExceptWith(clrExplicitScalarTypes);

            foreach (var clrMissingScalarType in clrMissingScalarTypes)
            {
                var apiMissingScalarTypeConfiguration = CreateApiScalarTypeConfiguration(clrMissingScalarType, apiPrecedenceStack);
                apiMutableSchema.ApiScalarTypeConfigurationDictionary.Add(clrMissingScalarType, apiMissingScalarTypeConfiguration);
            }
        }
        private static IApiSchema CreateApiSchema(ApiMutableSchema apiMutableSchema,
                                                  ApiPrecedenceStack apiPrecedenceStack)
        {
            Contract.Requires(apiMutableSchema != null);
            Contract.Requires(apiPrecedenceStack != null);

            var apiSchemaProxy = new ApiSchemaProxy();

            // Create API object types before other API types so implicit primitive property types (enums, scalars, etc.) are added to the mutable schema object.
            var apiObjectTypes      = CreateApiObjectTypes(apiMutableSchema, apiSchemaProxy);
            var apiEnumerationTypes = CreateApiEnumerationTypes(apiMutableSchema, apiPrecedenceStack, apiSchemaProxy);
            var apiScalarTypes      = CreateApiScalarTypes(apiMutableSchema, apiPrecedenceStack, apiSchemaProxy);

            var apiSchemaName = apiMutableSchema.ApiName;
            var apiSchema     = ApiTypeFactory.CreateApiSchema(apiSchemaName, apiEnumerationTypes, apiObjectTypes, apiScalarTypes);

            apiSchemaProxy.Initialize(apiSchema);

            return(apiSchema);
        }
        private static IEnumerable <TApiType> CreateApiTypes <TApiType>(ApiMutableSchema apiMutableSchema,
                                                                        ApiSchemaProxy apiSchemaProxy,
                                                                        IReadOnlyCollection <ApiTypeConfiguration> apiTypeConfigurations,
                                                                        ISet <Type> clrExcludedTypes)
            where TApiType : IApiNamedType
        {
            Contract.Requires(apiMutableSchema != null);
            Contract.Requires(apiSchemaProxy != null);
            Contract.Requires(apiTypeConfigurations != null);
            Contract.Requires(clrExcludedTypes != null);

            var apiTypeConfigurationsQuery = apiTypeConfigurations.AsEnumerable();

            if (clrExcludedTypes.Any())
            {
                var clrIncludedTypes = new HashSet <Type>(apiTypeConfigurations.Select(x => x.ClrType));
                clrIncludedTypes.ExceptWith(clrExcludedTypes);

                apiTypeConfigurationsQuery = apiTypeConfigurationsQuery.Where(x => clrIncludedTypes.Contains(x.ClrType));
            }

            var apiTypes = apiTypeConfigurationsQuery.Select(x =>
            {
                var apiMutableType = x.CreateApiMutableType(apiMutableSchema);
                var tuple          = new Tuple <ApiTypeConfiguration, ApiMutableType>(x, apiMutableType);
                return(tuple);
            })
                           .ToList()
                           .Select(tuple =>
            {
                var apiTypeConfiguration = tuple.Item1;
                var apiMutableType       = tuple.Item2;
                var apiType = apiTypeConfiguration.CreateApiType(apiMutableType, apiSchemaProxy);
                return(apiType);
            })
                           .Cast <TApiType>()
                           .OrderBy(x => x.ApiName)
                           .ToList();

            return(apiTypes);
        }
        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);
        }
        private Func <ApiSchemaFactorySettings, ApiMutableSchema> CreateApiMutableSchemaFactory()
        {
            ApiMutableSchema ApiMutableSchemaFactory(ApiSchemaFactorySettings apiSchemaFactorySettings)
            {
                // Apply conventions
                this.ApiPrecedenceStack.Push(ApiPrecedenceLevel.Convention);

                this.ApplyApiSchemaConventions(apiSchemaFactorySettings);

                this.ApiPrecedenceStack.Pop();

                // Create API schema context
                const string apiDefaultName   = ApiSchema.ApiDefaultName;
                var          apiMutableSchema = new ApiMutableSchema(apiSchemaFactorySettings)
                {
                    ApiName = apiDefaultName
                };

                return(apiMutableSchema);
            }

            return(ApiMutableSchemaFactory);
        }
 // INTERNAL METHODS /////////////////////////////////////////////////
 #region Methods
 internal abstract ApiMutableType CreateApiMutableType(ApiMutableSchema apiMutableSchema);