package net.kencochrane.raven;

import net.kencochrane.raven.dsn.Dsn;

import java.util.Collection;
import java.util.LinkedList;
import java.util.ServiceLoader;

/**
 * Factory in charge of creating {@link Raven} instances.
 * <p>
 * The factories register themselves through the {@link ServiceLoader} system.
 * </p>
 */
public abstract class RavenFactory {
    private static final ServiceLoader<RavenFactory> AUTO_REGISTERED_FACTORIES = ServiceLoader.load(RavenFactory.class);
    private static final Collection<RavenFactory> MANUALLY_REGISTERED_FACTORIES = new LinkedList<RavenFactory>();

    public static void registerFactory(RavenFactory ravenFactory) {
        MANUALLY_REGISTERED_FACTORIES.add(ravenFactory);
    }

    public static Raven ravenInstance() {
        return ravenInstance(Dsn.dsnLookup());
    }

    public static Raven ravenInstance(String dsn) {
        return ravenInstance(new Dsn(dsn));
    }

    public static Raven ravenInstance(Dsn dsn) {
        return ravenInstance(dsn, null);
    }

    public static Raven ravenInstance(Dsn dsn, String ravenFactoryName) {
        for (RavenFactory ravenFactory : MANUALLY_REGISTERED_FACTORIES) {
            if (ravenFactoryName != null && !ravenFactoryName.equals(ravenFactory.getClass().getName()))
                continue;

            Raven raven = ravenFactory.createRavenInstance(dsn);
            if (raven != null) {
                return raven;
            }
        }

        for (RavenFactory ravenFactory : AUTO_REGISTERED_FACTORIES) {
            if (ravenFactoryName != null && !ravenFactoryName.equals(ravenFactory.getClass().getName()))
                continue;

            Raven raven = ravenFactory.createRavenInstance(dsn);
            if (raven != null) {
                return raven;
            }
        }

        throw new IllegalStateException("Couldn't create a raven instance of '" + ravenFactoryName
                + "' for '" + dsn + "'");
    }

    public abstract Raven createRavenInstance(Dsn dsn);
}

@@ -62,16 +62,73 @@
 dsn.Dsn;
+%0Aimport org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;
 %0A%0Aimport
@@ -643,16 +643,102 @@
 tory%3E();
+%0A    private static final Logger logger = LoggerFactory.getLogger(RavenFactory.class);
 %0A%0A    pu
@@ -1431,32 +1431,142 @@
      continue;%0A%0A
+            logger.info(%22Found an appropriate Raven factory for '%7B%7D': '%7B%7D'%22, ravenFactoryName, ravenFactory);%0A
             Rave
@@ -1669,32 +1669,159 @@
   return raven;%0A
+            %7D else %7B%0A                logger.warn(%22The raven factory '%7B%7D' couldn't create an instance of Raven%22, ravenFactory);%0A
             %7D%0A  
@@ -2023,32 +2023,142 @@
      continue;%0A%0A
+            logger.info(%22Found an appropriate Raven factory for '%7B%7D': '%7B%7D'%22, ravenFactoryName, ravenFactory);%0A
             Rave
@@ -2261,32 +2261,159 @@
   return raven;%0A
+            %7D else %7B%0A                logger.warn(%22The raven factory '%7B%7D' couldn't create an instance of Raven%22, ravenFactory);%0A
             %7D%0A  

Add logs to track the usage of RavenFactory