package poussecafe.spring;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Configuration;
import poussecafe.context.MetaApplicationContext;
import poussecafe.context.StorableServices;
import poussecafe.process.DomainProcess;
import poussecafe.storable.IdentifiedStorableRepository;

@Configuration
public class SpringBridge implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
        pousseCafeContext = beanFactory.getBean(MetaApplicationContext.class);
        registerStorableServices();
        registerDomainProcesses();
        registerServices();
    }

    private ConfigurableListableBeanFactory beanFactory;

    private MetaApplicationContext pousseCafeContext;

    private void registerStorableServices() {
        for(StorableServices services : pousseCafeContext.getAllStorableServices()) {
            registeringFactory(services);
            registeringRepository(services);
        }
    }

    private void registeringFactory(StorableServices services) {
        String beanName = beanName(services.getFactory());
        logger.debug("Registering factory {}", services.getFactory().getClass().getSimpleName());
        registerInstance(beanName, services.getFactory());
    }

    private String beanName(Object instance) {
        return BEAN_NAME_PREFIX + instance.getClass().getName();
    }

    private static final String BEAN_NAME_PREFIX = "pousseCafe";

    private void registerInstance(String beanName, Object instance) {
        beanFactory.registerSingleton(beanName, instance);
    }

    private void registeringRepository(StorableServices services) {
        IdentifiedStorableRepository<?, ?, ?> repository = services.getRepository();
        String beanName = beanName(repository);
        logger.debug("Registering repository {}", repository.getClass().getSimpleName());
        registerInstance(beanName, repository);
    }

    private void registerDomainProcesses() {
        for(DomainProcess process : pousseCafeContext.getAllDomainProcesses()) {
            String beanName = beanName(process);
            logger.debug("Registering domain process {}", process.getClass().getSimpleName());
            registerInstance(beanName, process);
        }
    }

    private void registerServices() {
        for(Object service : pousseCafeContext.getAllServices()) {
            String beanName = beanName(service);
            logger.debug("Registering service {}", service.getClass().getSimpleName());
            registerInstance(beanName, service);
        }
    }

    private Logger logger = LoggerFactory.getLogger(getClass());
}

@@ -388,16 +388,59 @@
 rvices;%0A
+import poussecafe.messaging.MessageSender;%0A
 import p
@@ -825,24 +825,58 @@
 ext.class);%0A
+        registerCoreComponents();%0A
         regi
@@ -961,32 +961,225 @@
 vices();%0A    %7D%0A%0A
+    private void registerCoreComponents() %7B%0A        MessageSender messageSender = pousseCafeContext.getMessageSender();%0A        registerInstance(beanName(messageSender), messageSender);%0A    %7D%0A%0A
     private Conf

Add message sender to Spring application context.