// Path: src/main/java/de/aaschmid/gradle/plugins/cpd/internal/worker/CpdWorkParameters.java
// abstract class Report implements Serializable {
//     private final File destination;
// 
//     Report(File destination) {
//         this.destination = requireNonNull(destination, "'destination' must not be null for any report.");
//     }
// 
//     File getDestination() {
//         return destination;
//     }
// 
//     public static class Csv extends Report {
//         private final Character separator;
//         private final boolean includeLineCount;
// 
//         public Csv(File destination, Character separator, boolean includeLineCount) {
//             super(destination);
//             this.separator = separator;
//             this.includeLineCount = includeLineCount;
//         }
// 
//         Character getSeparator() {
//             return separator;
//         }
// 
//         boolean isIncludeLineCount() {
//             return includeLineCount;
//         }
//     }
// 
//     public static class Text extends Report {
//         private final String lineSeparator;
//         private final boolean trimLeadingCommonSourceWhitespaces;
// 
//         public Text(File destination, String lineSeparator, boolean trimLeadingCommonSourceWhitespaces) {
//             super(destination);
//             this.lineSeparator = lineSeparator;
//             this.trimLeadingCommonSourceWhitespaces = trimLeadingCommonSourceWhitespaces;
//         }
// 
//         String getLineSeparator() {
//             return lineSeparator;
//         }
// 
//         boolean isTrimLeadingCommonSourceWhitespaces() {
//             return trimLeadingCommonSourceWhitespaces;
//         }
//     }
// 
//     public static class Vs extends Report {
//         public Vs(File destination) {
//             super(destination);
//         }
//     }
// 
//     public static class Xml extends Report {
//         private final String encoding;
// 
//         public Xml(File destination, String encoding) {
//             super(destination);
//             this.encoding = encoding;
//         }
// 
//         String getEncoding() {
//             return encoding;
//         }
//     }
// }
// 
// Path: src/main/java/de/aaschmid/gradle/plugins/cpd/internal/worker/CpdWorkParameters.java
// public static class Xml extends Report {
//     private final String encoding;
// 
//     public Xml(File destination, String encoding) {
//         super(destination);
//         this.encoding = encoding;
//     }
// 
//     String getEncoding() {
//         return encoding;
//     }
// }


import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;
import de.aaschmid.gradle.plugins.cpd.internal.worker.CpdWorkParameters.Report;
import de.aaschmid.gradle.plugins.cpd.internal.worker.CpdWorkParameters.Report.Xml;
import net.sourceforge.pmd.cpd.CSVRenderer;
import net.sourceforge.pmd.cpd.Match;
import net.sourceforge.pmd.cpd.SimpleRenderer;
import net.sourceforge.pmd.cpd.VSRenderer;
import net.sourceforge.pmd.cpd.XMLRenderer;
import net.sourceforge.pmd.cpd.renderer.CPDRenderer;
import org.gradle.api.GradleException;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
package de.aaschmid.gradle.plugins.cpd.internal.worker;



class CpdReporter {

    private static final Logger logger = Logging.getLogger(CpdReporter.class);

    void generate(List<Report> reports, List<Match> matches) {
        if (logger.isInfoEnabled()) {
            logger.info("Generating reports");
        }
        for (Report report : reports) {
            CPDRenderer renderer = createRendererFor(report);
            try (FileWriter fileWriter = new FileWriter(report.getDestination())) {

                ClassLoader previousContextClassLoader = Thread.currentThread().getContextClassLoader();
                try {
                    // Workaround for Gradle Worker API using special class loader which Xerces dynamic implementation loading does not like
                    Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

                    renderer.render(matches.iterator(), fileWriter);
                } finally {
                    Thread.currentThread().setContextClassLoader(previousContextClassLoader);
                }
            } catch (IOException e) {
                throw new GradleException(e.getMessage(), e);
            }
        }
    }

    /**
     * Note: This cannot be implemented in {@link Report} subclasses because they must be independent of {@link
     * CPDRenderer} because only worker classloader knows about PMD / CPD library.
     *
     * @param report the configured reports used
     * @return a full configured {@link CPDRenderer} to generate a CPD single file reports.
     */
    CPDRenderer createRendererFor(Report report) {
// Path: src/main/java/de/aaschmid/gradle/plugins/cpd/internal/worker/CpdWorkParameters.java
// abstract class Report implements Serializable {
//     private final File destination;
// 
//     Report(File destination) {
//         this.destination = requireNonNull(destination, "'destination' must not be null for any report.");
//     }
// 
//     File getDestination() {
//         return destination;
//     }
// 
//     public static class Csv extends Report {
//         private final Character separator;
//         private final boolean includeLineCount;
// 
//         public Csv(File destination, Character separator, boolean includeLineCount) {
//             super(destination);
//             this.separator = separator;
//             this.includeLineCount = includeLineCount;
//         }
// 
//         Character getSeparator() {
//             return separator;
//         }
// 
//         boolean isIncludeLineCount() {
//             return includeLineCount;
//         }
//     }
// 
//     public static class Text extends Report {
//         private final String lineSeparator;
//         private final boolean trimLeadingCommonSourceWhitespaces;
// 
//         public Text(File destination, String lineSeparator, boolean trimLeadingCommonSourceWhitespaces) {
//             super(destination);
//             this.lineSeparator = lineSeparator;
//             this.trimLeadingCommonSourceWhitespaces = trimLeadingCommonSourceWhitespaces;
//         }
// 
//         String getLineSeparator() {
//             return lineSeparator;
//         }
// 
//         boolean isTrimLeadingCommonSourceWhitespaces() {
//             return trimLeadingCommonSourceWhitespaces;
//         }
//     }
// 
//     public static class Vs extends Report {
//         public Vs(File destination) {
//             super(destination);
//         }
//     }
// 
//     public static class Xml extends Report {
//         private final String encoding;
// 
//         public Xml(File destination, String encoding) {
//             super(destination);
//             this.encoding = encoding;
//         }
// 
//         String getEncoding() {
//             return encoding;
//         }
//     }
// }
// 
// Path: src/main/java/de/aaschmid/gradle/plugins/cpd/internal/worker/CpdWorkParameters.java
// public static class Xml extends Report {
//     private final String encoding;
// 
//     public Xml(File destination, String encoding) {
//         super(destination);
//         this.encoding = encoding;
//     }
// 
//     String getEncoding() {
//         return encoding;
//     }
// }


// Path: src/main/java/de/aaschmid/gradle/plugins/cpd/internal/worker/CpdReporter.java
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;
import de.aaschmid.gradle.plugins.cpd.internal.worker.CpdWorkParameters.Report;
import de.aaschmid.gradle.plugins.cpd.internal.worker.CpdWorkParameters.Report.Xml;
import net.sourceforge.pmd.cpd.CSVRenderer;
import net.sourceforge.pmd.cpd.Match;
import net.sourceforge.pmd.cpd.SimpleRenderer;
import net.sourceforge.pmd.cpd.VSRenderer;
import net.sourceforge.pmd.cpd.XMLRenderer;
import net.sourceforge.pmd.cpd.renderer.CPDRenderer;
import org.gradle.api.GradleException;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;

package de.aaschmid.gradle.plugins.cpd.internal.worker;



class CpdReporter {

    private static final Logger logger = Logging.getLogger(CpdReporter.class);

    void generate(List<Report> reports, List<Match> matches) {
        if (logger.isInfoEnabled()) {
            logger.info("Generating reports");
        }
        for (Report report : reports) {
            CPDRenderer renderer = createRendererFor(report);
            try (FileWriter fileWriter = new FileWriter(report.getDestination())) {

                ClassLoader previousContextClassLoader = Thread.currentThread().getContextClassLoader();
                try {
                    // Workaround for Gradle Worker API using special class loader which Xerces dynamic implementation loading does not like
                    Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

                    renderer.render(matches.iterator(), fileWriter);
                } finally {
                    Thread.currentThread().setContextClassLoader(previousContextClassLoader);
                }
            } catch (IOException e) {
                throw new GradleException(e.getMessage(), e);
            }
        }
    }

    /**
     * Note: This cannot be implemented in {@link Report} subclasses because they must be independent of {@link
     * CPDRenderer} because only worker classloader knows about PMD / CPD library.
     *
     * @param report the configured reports used
     * @return a full configured {@link CPDRenderer} to generate a CPD single file reports.
     */
    CPDRenderer createRendererFor(Report report) {
        if (report instanceof Report.Csv) {