package junitparams.internal.parameters;

import org.junit.runners.model.FrameworkMethod;

import junitparams.custom.ParametersProvider;
import junitparams.internal.annotation.CustomParametersDescriptor;
import junitparams.internal.annotation.FrameworkMethodAnnotations;

import java.lang.reflect.Constructor;

class ParametersFromCustomProvider implements ParametrizationStrategy {

    private final FrameworkMethodAnnotations frameworkMethodAnnotations;
    private final FrameworkMethod frameworkMethod;
    ParametersFromCustomProvider(FrameworkMethod frameworkMethod) {
        this.frameworkMethod=frameworkMethod;
        frameworkMethodAnnotations = new FrameworkMethodAnnotations(frameworkMethod);
    }

    @Override
    public boolean isApplicable() {
        return frameworkMethodAnnotations.hasCustomParameters();
    }

    @Override
    public Object[] getParameters() {
        CustomParametersDescriptor parameters = frameworkMethodAnnotations.getCustomParameters();
        ParametersProvider provider = instantiate(parameters.provider());
        provider.initialize(parameters.annotation());
        return provider.getParameters();
    }

    private ParametersProvider instantiate(Class<? extends ParametersProvider> providerClass) {
        Constructor<?>[] constructors = providerClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            Class<?>[] parameterTypes = constructor.getParameterTypes();
            if(parameterTypes.length==1){
                if(parameterTypes[0] == FrameworkMethod.class){
                    try {
                        return (ParametersProvider) constructor.newInstance(frameworkMethod);
                    } catch (Exception e) {
                        throw new RuntimeException("init error", e);
                    }
                }else{
                    throw new RuntimeException("init error,1-arg constructor parameter type must be FrameworkMethod!");
                }
            }else {
                try {
                    return (ParametersProvider) constructor.newInstance();
                } catch (Exception e) {
                    throw new RuntimeException("Your Provider class must have a public no-arg constructor!", e);
                }
            }
        }
        throw new RuntimeException("Your Provider class must have a public no-arg constructor!");
    }

}

@@ -302,16 +302,68 @@
 tructor;
+%0Aimport java.lang.reflect.InvocationTargetException;
 %0A%0Aclass 
@@ -1300,24 +1300,43 @@
 derClass) %7B%0A
+%0A        try %7B%0A    
         Cons
@@ -1344,19 +1344,44 @@
 ructor%3C?
-%3E%5B%5D
+ extends ParametersProvider%3E
  constru
@@ -1384,17 +1384,16 @@
 structor
-s
  = provi
@@ -1419,141 +1419,110 @@
 ctor
-s();%0A        for (Constructor%3C?%3E constructor : constructors) %7B%0A            Class%3C?%3E%5B%5D parameterTypes = constructor.getParameterTypes(
+(FrameworkMethod.class);%0A            return newParametersProviderInstance(constructor, frameworkMethod
 );%0A 
@@ -1532,105 +1532,96 @@
     
- 
-   if(parameterTypes.length==1)%7B%0A                if(parameterTypes%5B0%5D == FrameworkMethod.class)%7B
+%7D catch (NoSuchMethodException ignored) %7B%0A            // no framework constructor method
 %0A   
@@ -1617,36 +1617,35 @@
  method%0A        
-    
+%7D%0A%0A
         try %7B%0A  
@@ -1654,36 +1654,38 @@
         
-            return (
+Constructor%3C? extends 
 Paramete
@@ -1686,33 +1686,33 @@
 rametersProvider
-)
+%3E
  constructor.new
@@ -1711,370 +1711,417 @@
 ctor
-.newInstance(frameworkMethod);%0A                    %7D catch (Exception e) %7B%0A                        throw new RuntimeException(%22init error%22, e);%0A                    %7D%0A                %7Delse%7B%0A                    throw new RuntimeException(%22init error,1-arg constructor parameter type must be FrameworkMethod!%22);%0A                %7D%0A            %7Delse %7B%0A       
+ = providerClass.getConstructor();%0A            return newParametersProviderInstance(constructor);%0A        %7D catch (NoSuchMethodException ignored) %7B%0A            throw new RuntimeException(%22Your Provider class must have a public no-arg constructor!%22);%0A        %7D%0A    %7D%0A%0A    private ParametersProvider newParametersProviderInstance(Constructor%3C? extends ParametersProvider%3E constructor, Object... args) %7B%0A
         
  try
@@ -2112,25 +2112,24 @@
 ) %7B%0A        
- 
 try %7B%0A      
@@ -2138,43 +2138,14 @@
     
-      
-  
 return
- (ParametersProvider)
  con
@@ -2165,31 +2165,31 @@
 nstance(
-);%0A    
+args);%0A
         
     %7D ca
@@ -2176,28 +2176,24 @@
 s);%0A        
-    
 %7D catch (Exc
@@ -2189,16 +2189,32 @@
  catch (
+InvocationTarget
 Exceptio
@@ -2216,32 +2216,24 @@
 eption e) %7B%0A
-        
             
@@ -2264,196 +2264,182 @@
 on(%22
-Your Provider class must have a public no-arg constructor!%22, e);%0A                %7D%0A            %7D%0A        %7D%0A        throw new RuntimeException(%22Your Provider class must have a public no-arg
+Failed to initialise custom provider%22, e.getCause());%0A        %7D catch (Exception e) %7B%0A            throw new RuntimeException(%22Failed to invoke custom provider constructor %22 +
  con
@@ -2450,18 +2450,25 @@
 ctor
-!%22
 );%0A    
+  
+  %7D%0A    
 %7D
-%0A
 %0A%7D%0A

refactor instantiate method