// Path: dagger-servlet/src/main/java/dagger/ScopingObjectGraph.java
// public class ScopingObjectGraph extends ObjectGraph {
//     private final ObjectGraph objectGraph;
//     private final Map<Class<? extends Annotation>, Object[]> scopedModules;
// 
//     private final Scope requestScope = ServletScopes.REQUEST;
// 
//     ScopingObjectGraph(ObjectGraph objectGraph, Map<Class<? extends Annotation>, Object[]> scopedModules) {
//         this.objectGraph = objectGraph;
//         this.scopedModules = scopedModules;
//     }
// 
//     public static ScopingObjectGraph create(ObjectGraph objectGraph) {
//         return new ScopingObjectGraph(objectGraph, Maps.<Class<? extends Annotation>, Object[]>newHashMap());
//     }
// 
//     public ScopingObjectGraph addScopedModules(Class<? extends Annotation> scope, Object... modules) {
//         scopedModules.put(scope, modules);
//         return new ScopingObjectGraph(objectGraph, scopedModules);
//     }
// 
//     @Override
//     public <T> T get(Class<T> type) {
//         HttpServletRequest request = DaggerFilter.getRequest();
//         if (request == null && !ServletScopes.isNonHttpRequestScope()) {
//             return objectGraph.get(type);
//         }
// 
//         if (isRequestScoped(type)) {
//             return requestScope.scope(type, objectGraph, scopedModules.get(RequestScoped.class));
//         } else {
//             return objectGraph.get(type);
//         }
//     }
// 
//     @Override
//     public <T> T inject(T instance) {
//         HttpServletRequest request = DaggerFilter.getRequest();
//         if (request == null && !ServletScopes.isNonHttpRequestScope()) {
//             return objectGraph.inject(instance);
//         }
// 
//         if (isRequestScoped(instance.getClass())) {
//             return requestScope.scopeInstance(instance, objectGraph, scopedModules.get(RequestScoped.class));
//         } else {
//             return objectGraph.inject(instance);
//         }
//     }
// 
//     @Override
//     public ObjectGraph plus(Object... modules) {
//         return new ScopingObjectGraph(objectGraph.plus(modules), scopedModules);
//     }
// 
//     @Override
//     public void validate() {
//         objectGraph.validate();
// 
//         for (Object[] modules : scopedModules.values()) {
//             objectGraph.plus(modules).validate();
//         }
//     }
// 
//     // TODO: Add validation of classes and objects so we can make sure the filter/servlet classes have injections
//     // and fail early instead of when we try to inject it on an actual request.
// 
//     @Override
//     public void injectStatics() {
//         // Only need to inject on the base object graph. Plused modules do not do static injection.
//         objectGraph.injectStatics();
//     }
// 
//     private <T> boolean isRequestScoped(Class<T> type) {
//         Object[] requestScopedModules = scopedModules.get(RequestScoped.class);
//         for (Object requestScopedModule : requestScopedModules) {
//             Module module;
//             if (requestScopedModule instanceof Class<?>) {
//                 module = ((Class<?>) requestScopedModule).getAnnotation(Module.class);
//             } else {
//                 module = requestScopedModule.getClass().getAnnotation(Module.class);
//             }
// 
//             if (arrayContains(module.injects(), type)) {
//                 return true;
//             }
//         }
// 
//         return false;
//     }
// 
//     private static <T> boolean arrayContains(final T[] array, final T value) {
//         for (final T element : array) {
//             if (element == value || (value != null && value.equals(element))) {
//                 return true;
//             }
//         }
// 
//         return false;
//     }
// }


import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import dagger.Module;
import dagger.ObjectGraph;
import dagger.Provides;
import dagger.ScopingObjectGraph;
import org.testng.annotations.Test;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.fail;
                    ObjectGraph.class
            },
            includes = {
                    ServletModule.class
            }
    )
    static class TestAppModule {
    }

    @Module(
            injects = {
                    SomeObject.class
            },
            includes = {
                    ServletRequestModule.class
            }
    )
    static class TestRequestModule {
        @Provides
        @Named(SomeObject.INVALID)
        String provideInvalidString() {
            return SHOULDNEVERBESEEN;
        }
    }

    @Test
    public final void testNonHttpRequestScopedCallable()
            throws ServletException, IOException, InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        ObjectGraph baseGraph = ObjectGraph.create(TestAppModule.class);
// Path: dagger-servlet/src/main/java/dagger/ScopingObjectGraph.java
// public class ScopingObjectGraph extends ObjectGraph {
//     private final ObjectGraph objectGraph;
//     private final Map<Class<? extends Annotation>, Object[]> scopedModules;
// 
//     private final Scope requestScope = ServletScopes.REQUEST;
// 
//     ScopingObjectGraph(ObjectGraph objectGraph, Map<Class<? extends Annotation>, Object[]> scopedModules) {
//         this.objectGraph = objectGraph;
//         this.scopedModules = scopedModules;
//     }
// 
//     public static ScopingObjectGraph create(ObjectGraph objectGraph) {
//         return new ScopingObjectGraph(objectGraph, Maps.<Class<? extends Annotation>, Object[]>newHashMap());
//     }
// 
//     public ScopingObjectGraph addScopedModules(Class<? extends Annotation> scope, Object... modules) {
//         scopedModules.put(scope, modules);
//         return new ScopingObjectGraph(objectGraph, scopedModules);
//     }
// 
//     @Override
//     public <T> T get(Class<T> type) {
//         HttpServletRequest request = DaggerFilter.getRequest();
//         if (request == null && !ServletScopes.isNonHttpRequestScope()) {
//             return objectGraph.get(type);
//         }
// 
//         if (isRequestScoped(type)) {
//             return requestScope.scope(type, objectGraph, scopedModules.get(RequestScoped.class));
//         } else {
//             return objectGraph.get(type);
//         }
//     }
// 
//     @Override
//     public <T> T inject(T instance) {
//         HttpServletRequest request = DaggerFilter.getRequest();
//         if (request == null && !ServletScopes.isNonHttpRequestScope()) {
//             return objectGraph.inject(instance);
//         }
// 
//         if (isRequestScoped(instance.getClass())) {
//             return requestScope.scopeInstance(instance, objectGraph, scopedModules.get(RequestScoped.class));
//         } else {
//             return objectGraph.inject(instance);
//         }
//     }
// 
//     @Override
//     public ObjectGraph plus(Object... modules) {
//         return new ScopingObjectGraph(objectGraph.plus(modules), scopedModules);
//     }
// 
//     @Override
//     public void validate() {
//         objectGraph.validate();
// 
//         for (Object[] modules : scopedModules.values()) {
//             objectGraph.plus(modules).validate();
//         }
//     }
// 
//     // TODO: Add validation of classes and objects so we can make sure the filter/servlet classes have injections
//     // and fail early instead of when we try to inject it on an actual request.
// 
//     @Override
//     public void injectStatics() {
//         // Only need to inject on the base object graph. Plused modules do not do static injection.
//         objectGraph.injectStatics();
//     }
// 
//     private <T> boolean isRequestScoped(Class<T> type) {
//         Object[] requestScopedModules = scopedModules.get(RequestScoped.class);
//         for (Object requestScopedModule : requestScopedModules) {
//             Module module;
//             if (requestScopedModule instanceof Class<?>) {
//                 module = ((Class<?>) requestScopedModule).getAnnotation(Module.class);
//             } else {
//                 module = requestScopedModule.getClass().getAnnotation(Module.class);
//             }
// 
//             if (arrayContains(module.injects(), type)) {
//                 return true;
//             }
//         }
// 
//         return false;
//     }
// 
//     private static <T> boolean arrayContains(final T[] array, final T value) {
//         for (final T element : array) {
//             if (element == value || (value != null && value.equals(element))) {
//                 return true;
//             }
//         }
// 
//         return false;
//     }
// }


// Path: dagger-servlet/src/test/java/com/leacox/dagger/servlet/ScopeRequestIntegrationTest.java
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import dagger.Module;
import dagger.ObjectGraph;
import dagger.Provides;
import dagger.ScopingObjectGraph;
import org.testng.annotations.Test;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.fail;

                    ObjectGraph.class
            },
            includes = {
                    ServletModule.class
            }
    )
    static class TestAppModule {
    }

    @Module(
            injects = {
                    SomeObject.class
            },
            includes = {
                    ServletRequestModule.class
            }
    )
    static class TestRequestModule {
        @Provides
        @Named(SomeObject.INVALID)
        String provideInvalidString() {
            return SHOULDNEVERBESEEN;
        }
    }

    @Test
    public final void testNonHttpRequestScopedCallable()
            throws ServletException, IOException, InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        ObjectGraph baseGraph = ObjectGraph.create(TestAppModule.class);
        ObjectGraph scopingGraph = ScopingObjectGraph.create(baseGraph)