<commit_before>﻿using Common.Logging;
using Common.Logging.Configuration;
using Common.Logging.NLog;
using IntegrationEngine.Api;
using IntegrationEngine.Core.Configuration;
using IntegrationEngine.Core.Elasticsearch;
using IntegrationEngine.Core.IntegrationPoint;
using IntegrationEngine.Core.Jobs;
using IntegrationEngine.Core.Mail;
using IntegrationEngine.Core.MessageQueue;
using IntegrationEngine.Core.R;
using IntegrationEngine.Core.Storage;
using IntegrationEngine.JobProcessor;
using IntegrationEngine.Scheduler;
using Microsoft.Practices.ObjectBuilder2;
using Microsoft.Practices.Unity;
using Nest;
using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using IntegrationEngine.Core.ServiceStack;

namespace IntegrationEngine
{
    public class EngineHostCompositionRoot : IDisposable
    {
        public IUnityContainer Container { get; set; }
        public IEngineConfiguration EngineConfiguration { get; set; }
        public IList<Type> IntegrationJobTypes { get; set; }
        public ILog Log { get; set; }
        public IWebApiApplication WebApiApplication { get; set; }

        public EngineHostCompositionRoot()
        {}

        public void Configure(IList<Assembly> assembliesWithJobs)
        {
            Container = ContainerSingleton.GetContainer();
            IntegrationJobTypes = assembliesWithJobs
                        .SelectMany(x => x.GetTypes())
                        .Where(x => typeof(IIntegrationJob).IsAssignableFrom(x) && x.IsClass)
                        .ToList();
            LoadConfiguration();
            SetupLogging();
            RegisterIntegrationPoints();
            RegisterIntegrationJobs();
            SetupRScriptRunner();
            SetupElasticsearchRepository();
            SetupThreadedListenerManager();
            SetupEngineScheduler();
            SetupWebApi();
        }

        public void LoadConfiguration()
        {
            try
            {
                new EngineConfiguration();
            }
            catch (Exception exception)
            {
                throw new Exception("Could not read configuration.", exception);
            }
            Container.RegisterType<IEngineConfiguration, EngineConfiguration>();
            EngineConfiguration = Container.Resolve<IEngineConfiguration>();
        }

        public void SetupLogging()
        {
            var config = EngineConfiguration.NLogAdapter;
            var properties = new NameValueCollection();
            properties["configType"] = config.ConfigType;
            properties["configFile"] = config.ConfigFile;
            Common.Logging.LogManager.Adapter = new NLogLoggerFactoryAdapter(properties);  
            Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        }

        public void SetupDatabaseRepository(IntegrationEngineContext integrationEngineContext)
        {
            Container.RegisterInstance<IDatabaseRepository>(new DatabaseRepository(integrationEngineContext));
        }

        public void RegisterIntegrationPoints()
        {
            Container.RegisterType<Elasticsearch.Net.Connection.IConnection, Elasticsearch.Net.Connection.HttpConnection>();
            Container.RegisterType<INestSerializer, NestSerializer>();
            Container.RegisterType<Elasticsearch.Net.Connection.ITransport, Elasticsearch.Net.Connection.Transport>();
            Container.RegisterType<IConnectionSettingsValues, ConnectionSettings>();
            foreach (var config in EngineConfiguration.IntegrationPoints.Mail) {
                Container.RegisterType<IMailConfiguration, MailConfiguration>(config.IntegrationPointName,
                    new InjectionConstructor(
                        new ResolvedParameter<IEngineConfiguration>(),
                        config.IntegrationPointName
                    )
                );
                Container.RegisterType<IMailClient, MailClient>(config.IntegrationPointName, new InjectionConstructor(config));
            }

            Func<IUnityContainer, Type, string, object> elasticClientFactory = (container, type, configName) => {
                var config = container.Resolve<IElasticsearchConfiguration>(configName);
                var serverUri = new UriBuilder(config.Protocol, config.HostName, config.Port).Uri;
                var settings = new ConnectionSettings(serverUri, config.DefaultIndex);
                return new ElasticClient(settings);
            };
            foreach (var config in EngineConfiguration.IntegrationPoints.Elasticsearch) {
                Container.RegisterType<IElasticsearchConfiguration, ElasticsearchConfiguration>(config.IntegrationPointName,
                    new InjectionConstructor(
                        new ResolvedParameter<IEngineConfiguration>(),
                        config.IntegrationPointName
                    )
                );
                Container.RegisterType<IElasticClient, ElasticClientAdapter>(config.IntegrationPointName, 
                    new InjectionFactory(elasticClientFactory));
            }
            foreach (var config in EngineConfiguration.IntegrationPoints.RabbitMQ) {
                Container.RegisterType<IRabbitMQConfiguration, RabbitMQConfiguration>(config.IntegrationPointName,
                    new InjectionConstructor(
                        new ResolvedParameter<IEngineConfiguration>(),
                        config.IntegrationPointName
                    )
                );
                Container.RegisterType<IRabbitMQClient, RabbitMQClient>(config.IntegrationPointName, new InjectionConstructor(config));
            }
            foreach (var config in EngineConfiguration.IntegrationPoints.JsonService) {
                Container.RegisterType<IJsonServiceConfiguration, JsonServiceConfiguration>(config.IntegrationPointName,
                    new InjectionConstructor(
                        new ResolvedParameter<IEngineConfiguration>(),
                        config.IntegrationPointName
                    )
                );
                Container.RegisterType<IJsonServiceClient, JsonServiceClientAdapter>(config.IntegrationPointName, new InjectionConstructor(config));
            }
        }

        /// <summary>
        /// Registers the integration jobs.
        /// Resolve the integration point type (specified in a job's parameters).
        /// Configure the integration point type with a configuration, based on a parameter's name.                    
        /// </summary>
        public void RegisterIntegrationJobs()
        {<commit_msg>DRYout config registration<commit_after>﻿using Common.Logging;
using Common.Logging.Configuration;
using Common.Logging.NLog;
using IntegrationEngine.Api;
using IntegrationEngine.Core.Configuration;
using IntegrationEngine.Core.Elasticsearch;
using IntegrationEngine.Core.IntegrationPoint;
using IntegrationEngine.Core.Jobs;
using IntegrationEngine.Core.Mail;
using IntegrationEngine.Core.MessageQueue;
using IntegrationEngine.Core.R;
using IntegrationEngine.Core.Storage;
using IntegrationEngine.JobProcessor;
using IntegrationEngine.Scheduler;
using Microsoft.Practices.ObjectBuilder2;
using Microsoft.Practices.Unity;
using Nest;
using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using IntegrationEngine.Core.ServiceStack;

namespace IntegrationEngine
{
    public class EngineHostCompositionRoot : IDisposable
    {
        public IUnityContainer Container { get; set; }
        public IEngineConfiguration EngineConfiguration { get; set; }
        public IList<Type> IntegrationJobTypes { get; set; }
        public ILog Log { get; set; }
        public IWebApiApplication WebApiApplication { get; set; }

        public EngineHostCompositionRoot()
        {}

        public void Configure(IList<Assembly> assembliesWithJobs)
        {
            Container = ContainerSingleton.GetContainer();
            IntegrationJobTypes = assembliesWithJobs
                        .SelectMany(x => x.GetTypes())
                        .Where(x => typeof(IIntegrationJob).IsAssignableFrom(x) && x.IsClass)
                        .ToList();
            LoadConfiguration();
            SetupLogging();
            RegisterIntegrationPoints();
            RegisterIntegrationJobs();
            SetupRScriptRunner();
            SetupElasticsearchRepository();
            SetupThreadedListenerManager();
            SetupEngineScheduler();
            SetupWebApi();
        }

        public void LoadConfiguration()
        {
            try
            {
                new EngineConfiguration();
            }
            catch (Exception exception)
            {
                throw new Exception("Could not read configuration.", exception);
            }
            Container.RegisterType<IEngineConfiguration, EngineConfiguration>();
            EngineConfiguration = Container.Resolve<IEngineConfiguration>();
        }

        public void SetupLogging()
        {
            var config = EngineConfiguration.NLogAdapter;
            var properties = new NameValueCollection();
            properties["configType"] = config.ConfigType;
            properties["configFile"] = config.ConfigFile;
            Common.Logging.LogManager.Adapter = new NLogLoggerFactoryAdapter(properties);  
            Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        }

        public void SetupDatabaseRepository(IntegrationEngineContext integrationEngineContext)
        {
            Container.RegisterInstance<IDatabaseRepository>(new DatabaseRepository(integrationEngineContext));
        }

        void RegisterConfig(Type from, Type to, string integrationPointName)
        {
            Container.RegisterType(from, to, integrationPointName,
                new InjectionConstructor(new ResolvedParameter<IEngineConfiguration>(), integrationPointName)
            );
        }

        public void RegisterIntegrationPoints()
        {
            Container.RegisterType<Elasticsearch.Net.Connection.IConnection, Elasticsearch.Net.Connection.HttpConnection>();
            Container.RegisterType<INestSerializer, NestSerializer>();
            Container.RegisterType<Elasticsearch.Net.Connection.ITransport, Elasticsearch.Net.Connection.Transport>();
            Container.RegisterType<IConnectionSettingsValues, ConnectionSettings>();
            foreach (var config in EngineConfiguration.IntegrationPoints.Mail) {
                RegisterConfig(typeof(IMailConfiguration), typeof(MailConfiguration), config.IntegrationPointName);
                Container.RegisterType<IMailClient, MailClient>(config.IntegrationPointName, new InjectionConstructor(config));
            }

            Func<IUnityContainer, Type, string, object> elasticClientFactory = (container, type, configName) => {
                var config = container.Resolve<IElasticsearchConfiguration>(configName);
                var serverUri = new UriBuilder(config.Protocol, config.HostName, config.Port).Uri;
                var settings = new ConnectionSettings(serverUri, config.DefaultIndex);
                return new ElasticClient(settings);
            };
            foreach (var config in EngineConfiguration.IntegrationPoints.Elasticsearch) {
                RegisterConfig(typeof(IElasticsearchConfiguration), typeof(ElasticsearchConfiguration), config.IntegrationPointName);
                Container.RegisterType<IElasticClient, ElasticClientAdapter>(config.IntegrationPointName, new InjectionFactory(elasticClientFactory));
            }
            foreach (var config in EngineConfiguration.IntegrationPoints.RabbitMQ) {
                RegisterConfig(typeof(IRabbitMQConfiguration), typeof(RabbitMQConfiguration), config.IntegrationPointName);
                Container.RegisterType<IRabbitMQClient, RabbitMQClient>(config.IntegrationPointName, new InjectionConstructor(config));
            }
            foreach (var config in EngineConfiguration.IntegrationPoints.JsonService) {
                RegisterConfig(typeof(IJsonServiceConfiguration), typeof(JsonServiceConfiguration), config.IntegrationPointName);
                Container.RegisterType<IJsonServiceClient, JsonServiceClientAdapter>(config.IntegrationPointName, new InjectionConstructor(config));
            }
        }

        /// <summary>
        /// Registers the integration jobs.
        /// Resolve the integration point type (specified in a job's parameters).
        /// Configure the integration point type with a configuration, based on a parameter's name.                    
        /// </summary>
        public void RegisterIntegrationJobs()
        {
{'fraction_non_alphanumeric': 0.07687529119428482, 'fraction_numerical': 0.0006212144742972511, 'mean_word_length': 2.6371081615362892, 'pattern_counts': {'":': 0, '<': 46, '<?xml version=': 0, '>': 52, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5442394', 'n_tokens_mistral': 2928, 'n_tokens_neox': 2781, 'n_words': 566}