// Path: src/main/java/io/github/sskorol/model/DataSupplierMetaData.java
// public class DataSupplierMetaData {
// 
//     @Getter
//     private final List<Object[]> testData;
//     private final boolean transpose;
//     private final boolean flatMap;
//     private final int[] indices;
//     @Getter
//     private final TestNGMethod testNGMethod;
// 
//     public DataSupplierMetaData(final ITestContext context, final ITestNGMethod testMethod) {
//         this.testNGMethod = new TestNGMethod(context, testMethod);
//         this.transpose = testNGMethod.getDataSupplierArg(DataSupplier::transpose, false);
//         this.flatMap = testNGMethod.getDataSupplierArg(DataSupplier::flatMap, false);
//         this.indices = testNGMethod.getDataSupplierArg(DataSupplier::indices, new int[0]);
//         this.testData = transform();
//     }
// 
//     private List<Object[]> transform() {
//         var data = streamOf(obtainReturnValue()).toList();
//         var indicesList = indicesList(data.size());
//         var wrappedReturnValue = EntryStream.of(data).filterKeys(indicesList::contains).values();
// 
//         if (transpose) {
//             return singletonList(flatMap
//                     ? wrappedReturnValue.flatMap(ReflectionUtils::streamOf).toArray()
//                     : wrappedReturnValue.toArray());
//         }
// 
//         return wrappedReturnValue.map(ob -> flatMap ? streamOf(ob).toArray() : new Object[]{ob}).toList();
//     }
// 
//     private Object obtainReturnValue() {
//         return invokeDataSupplier(testNGMethod.getDataSupplierMetaData());
//     }
// 
//     private List<Integer> indicesList(final int collectionSize) {
//         return ofNullable(indices)
//                 .filter(indicesArray -> indicesArray.length > 0)
//                 .map(IntStreamEx::of)
//                 .orElseGet(() -> IntStreamEx.range(0, collectionSize))
//                 .boxed()
//                 .toList();
//     }
// }
// 
// Path: src/main/java/io/github/sskorol/utils/ReflectionUtils.java
// public static DataSupplier getDataSupplierAnnotation(final Class<?> targetClass, final String targetMethodName) {
//     return Try.of(() -> getDataSupplierMethod(targetClass, targetMethodName))
//             .map(method -> method.getDeclaredAnnotation(DataSupplier.class))
//             .filter(Objects::nonNull)
//             .getOrElse((DataSupplier) null);
// }
// 
// Path: src/main/java/io/github/sskorol/utils/ReflectionUtils.java
// @SuppressWarnings("unchecked")
// public static <T> Class<T> getDataSupplierClass(final IDataProvidable annotation, final Class<T> testClass,
//                                                 final Method testMethod) {
//     return ofNullable(annotation.getDataProviderClass())
//             .map(Class.class::cast)
//             .orElseGet(() -> findParentDataSupplierClass(testMethod, testClass));
// }


import io.github.sskorol.model.DataSupplierMetaData;
import org.testng.*;
import org.testng.annotations.*;
import org.testng.internal.annotations.IDataProvidable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Iterator;
import static io.github.sskorol.utils.ReflectionUtils.getDataSupplierAnnotation;
import static io.github.sskorol.utils.ReflectionUtils.getDataSupplierClass;
import static java.util.Objects.nonNull;
package io.github.sskorol.core;




/**
 * Core listener which transforms custom DataSupplier format to common TestNG DataProvider.
 */
public class DataProviderTransformer implements IAnnotationTransformer {

    @DataProvider
    public Iterator<Object[]> supplySeqData(final ITestContext context, final ITestNGMethod testMethod) {
        return getMetaData(context, testMethod).getTestData().iterator();
    }

    @DataProvider(parallel = true)
    public Iterator<Object[]> supplyParallelData(final ITestContext context, final ITestNGMethod testMethod) {
        return getMetaData(context, testMethod).getTestData().iterator();
    }

    @Override
    public void transform(final ITestAnnotation annotation, final Class testClass,
                          final Constructor testConstructor, final Method testMethod) {
        assignCustomDataSupplier(annotation, testMethod, testClass);
    }

    @Override
    public void transform(final IFactoryAnnotation annotation, final Method testMethod) {
        assignCustomDataSupplier(annotation, testMethod, null);
    }

// Path: src/main/java/io/github/sskorol/model/DataSupplierMetaData.java
// public class DataSupplierMetaData {
// 
//     @Getter
//     private final List<Object[]> testData;
//     private final boolean transpose;
//     private final boolean flatMap;
//     private final int[] indices;
//     @Getter
//     private final TestNGMethod testNGMethod;
// 
//     public DataSupplierMetaData(final ITestContext context, final ITestNGMethod testMethod) {
//         this.testNGMethod = new TestNGMethod(context, testMethod);
//         this.transpose = testNGMethod.getDataSupplierArg(DataSupplier::transpose, false);
//         this.flatMap = testNGMethod.getDataSupplierArg(DataSupplier::flatMap, false);
//         this.indices = testNGMethod.getDataSupplierArg(DataSupplier::indices, new int[0]);
//         this.testData = transform();
//     }
// 
//     private List<Object[]> transform() {
//         var data = streamOf(obtainReturnValue()).toList();
//         var indicesList = indicesList(data.size());
//         var wrappedReturnValue = EntryStream.of(data).filterKeys(indicesList::contains).values();
// 
//         if (transpose) {
//             return singletonList(flatMap
//                     ? wrappedReturnValue.flatMap(ReflectionUtils::streamOf).toArray()
//                     : wrappedReturnValue.toArray());
//         }
// 
//         return wrappedReturnValue.map(ob -> flatMap ? streamOf(ob).toArray() : new Object[]{ob}).toList();
//     }
// 
//     private Object obtainReturnValue() {
//         return invokeDataSupplier(testNGMethod.getDataSupplierMetaData());
//     }
// 
//     private List<Integer> indicesList(final int collectionSize) {
//         return ofNullable(indices)
//                 .filter(indicesArray -> indicesArray.length > 0)
//                 .map(IntStreamEx::of)
//                 .orElseGet(() -> IntStreamEx.range(0, collectionSize))
//                 .boxed()
//                 .toList();
//     }
// }
// 
// Path: src/main/java/io/github/sskorol/utils/ReflectionUtils.java
// public static DataSupplier getDataSupplierAnnotation(final Class<?> targetClass, final String targetMethodName) {
//     return Try.of(() -> getDataSupplierMethod(targetClass, targetMethodName))
//             .map(method -> method.getDeclaredAnnotation(DataSupplier.class))
//             .filter(Objects::nonNull)
//             .getOrElse((DataSupplier) null);
// }
// 
// Path: src/main/java/io/github/sskorol/utils/ReflectionUtils.java
// @SuppressWarnings("unchecked")
// public static <T> Class<T> getDataSupplierClass(final IDataProvidable annotation, final Class<T> testClass,
//                                                 final Method testMethod) {
//     return ofNullable(annotation.getDataProviderClass())
//             .map(Class.class::cast)
//             .orElseGet(() -> findParentDataSupplierClass(testMethod, testClass));
// }


// Path: src/main/java/io/github/sskorol/core/DataProviderTransformer.java
import io.github.sskorol.model.DataSupplierMetaData;
import org.testng.*;
import org.testng.annotations.*;
import org.testng.internal.annotations.IDataProvidable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Iterator;
import static io.github.sskorol.utils.ReflectionUtils.getDataSupplierAnnotation;
import static io.github.sskorol.utils.ReflectionUtils.getDataSupplierClass;
import static java.util.Objects.nonNull;

package io.github.sskorol.core;




/**
 * Core listener which transforms custom DataSupplier format to common TestNG DataProvider.
 */
public class DataProviderTransformer implements IAnnotationTransformer {

    @DataProvider
    public Iterator<Object[]> supplySeqData(final ITestContext context, final ITestNGMethod testMethod) {
        return getMetaData(context, testMethod).getTestData().iterator();
    }

    @DataProvider(parallel = true)
    public Iterator<Object[]> supplyParallelData(final ITestContext context, final ITestNGMethod testMethod) {
        return getMetaData(context, testMethod).getTestData().iterator();
    }

    @Override
    public void transform(final ITestAnnotation annotation, final Class testClass,
                          final Constructor testConstructor, final Method testMethod) {
        assignCustomDataSupplier(annotation, testMethod, testClass);
    }

    @Override
    public void transform(final IFactoryAnnotation annotation, final Method testMethod) {
        assignCustomDataSupplier(annotation, testMethod, null);
    }

    private DataSupplierMetaData getMetaData(final ITestContext context, final ITestNGMethod testMethod) {