package com.tngtech.jgiven.config;

import java.util.concurrent.ExecutionException;

import com.google.common.base.Throwables;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.tngtech.jgiven.annotation.JGivenConfiguration;
import com.tngtech.jgiven.impl.util.ReflectionUtil;

public class ConfigurationUtil {

    private static final LoadingCache<Class<?>, AbstractJGivenConfiguration> configurations = CacheBuilder.newBuilder().build(
        new CacheLoader<Class<?>, AbstractJGivenConfiguration>() {
            @Override
            public AbstractJGivenConfiguration load( Class<?> key ) throws Exception {
                AbstractJGivenConfiguration result = (AbstractJGivenConfiguration) ReflectionUtil.newInstance( key );
                result.configure();
                return result;
            }
        } );

    public static AbstractJGivenConfiguration getConfiguration( Class<? extends Object> testClass ) {
        JGivenConfiguration annotation = testClass.getAnnotation( JGivenConfiguration.class );
        Class<?> configuration;
        if( annotation == null ) {
            configuration = DefaultConfiguration.class;
        } else {
            configuration = annotation.value();
        }

        try {
            return configurations.get( configuration );
        } catch( ExecutionException e ) {
            throw Throwables.propagate( e.getCause() );
        }
    }
}

@@ -33,99 +33,8 @@
 g;%0A%0A
-import java.util.concurrent.ExecutionException;%0A%0Aimport com.google.common.base.Throwables;%0A
 impo
@@ -273,16 +273,92 @@
 onUtil;%0A
+import java.util.Optional;%0Aimport java.util.concurrent.ExecutionException;%0A%0A
 %0Apublic 
@@ -477,16 +477,24 @@
 ations =
+%0A       
  CacheBu
@@ -527,16 +527,20 @@
         
+  
+  
 new Cach
@@ -602,16 +602,20 @@
         
+    
 @Overrid
@@ -624,24 +624,28 @@
             
+   
+ 
 public Abstr
@@ -672,17 +672,16 @@
 on load(
- 
 Class%3C?%3E
@@ -688,30 +688,16 @@
  key
- 
 ) 
-throws Exception %7B%0A
+%7B%0A    
     
@@ -806,16 +806,18 @@
 nce(
- 
 key
- 
 );%0A
+    
     
@@ -844,24 +844,28 @@
 onfigure();%0A
+    
             
@@ -891,24 +891,28 @@
             
+    
 %7D%0A        %7D 
@@ -913,18 +913,21 @@
     
-%7D
  
+   %7D
 );%0A%0A    
 publ
@@ -926,21 +926,98 @@
     
-public static
+@SuppressWarnings(%7B%22unchecked%22%7D)%0A    public static %3CA extends AbstractJGivenConfiguration%3E
  Abs
@@ -1058,24 +1058,32 @@
 uration(
+%0A       
  Class%3C?
  extends
@@ -1078,23 +1078,8 @@
 ss%3C?
- extends Object
 %3E te
@@ -1085,17 +1085,16 @@
 estClass
- 
 ) %7B%0A    
@@ -1101,50 +1101,135 @@
     
-JGivenConfiguration annotation = testClass
+Class%3C? extends AbstractJGivenConfiguration%3E configuration = Optional.ofNullable(testClass)%0A            .map(content -%3E content
 .get
@@ -1239,17 +1239,16 @@
 otation(
- 
 JGivenCo
@@ -1264,19 +1264,18 @@
 on.class
- );
+))
 %0A       
@@ -1279,197 +1279,115 @@
     
+    .map(content -%3E (
 Class%3C
-?%3E
+A%3E)
  con
-figuration;%0A        if( annotation == null ) %7B%0A            configuration = DefaultConfiguration.class;%0A        %7D else %7B%0A            configuration = annotation.value();%0A        %7D
+tent.value())%0A            .orElse((Class%3CA%3E) DefaultConfiguration.class);
 %0A%0A  
@@ -1436,17 +1436,16 @@
 ons.get(
- 
 configur
@@ -1449,17 +1449,16 @@
 guration
- 
 );%0A     
@@ -1467,18 +1467,18 @@
  %7D catch
-(
  
+(
 Executio
@@ -1489,17 +1489,16 @@
 eption e
- 
 ) %7B%0A    
@@ -1515,30 +1515,29 @@
 row 
-Throwables.propagate( 
+new RuntimeException(
 e.ge
@@ -1544,17 +1544,16 @@
 tCause()
- 
 );%0A     

Introduce optional into the configuration util to simplify the code