// 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;
//         }
//     }
// }


import java.io.File;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Properties;
import javax.inject.Inject;
import de.aaschmid.gradle.plugins.cpd.internal.worker.CpdWorkParameters.Report;
import net.sourceforge.pmd.cpd.AnyLanguage;
import net.sourceforge.pmd.cpd.CPDConfiguration;
import net.sourceforge.pmd.cpd.Language;
import net.sourceforge.pmd.cpd.LanguageFactory;
import net.sourceforge.pmd.cpd.Match;
import net.sourceforge.pmd.cpd.Tokenizer;
import org.gradle.api.GradleException;
import org.gradle.workers.WorkAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
    // Visible for testing
    CpdAction(CpdExecutor executor, CpdReporter reporter) {
        this.executor = executor;
        this.reporter = reporter;
    }

    @Override
    public void execute() {
        List<Match> matches = executor.run(createCpdConfiguration(getParameters()), getParameters().getSourceFiles().getFiles());
        reporter.generate(getParameters().getReportParameters().get(), matches);
        logResult(matches);
    }

    private CPDConfiguration createCpdConfiguration(CpdWorkParameters config) {
        CPDConfiguration result = new CPDConfiguration();
        result.setEncoding(config.getEncoding().get());
        result.setLanguage(createLanguage(config.getLanguage().get(), createLanguageProperties(config)));
        result.setMinimumTileSize(config.getMinimumTokenCount().get());
        result.setSkipDuplicates(config.getSkipDuplicateFiles().get());
        result.setSkipLexicalErrors(config.getSkipLexicalErrors().get());
        return result;
    }

    private void logResult(List<Match> matches) {
        if (matches.isEmpty()) {
            if (logger.isInfoEnabled()) {
                logger.info("No duplicates over {} tokens found.", getParameters().getMinimumTokenCount().get());
            }
        } else {
            String message = "CPD found duplicate code.";
// 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/CpdAction.java
import java.io.File;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Properties;
import javax.inject.Inject;
import de.aaschmid.gradle.plugins.cpd.internal.worker.CpdWorkParameters.Report;
import net.sourceforge.pmd.cpd.AnyLanguage;
import net.sourceforge.pmd.cpd.CPDConfiguration;
import net.sourceforge.pmd.cpd.Language;
import net.sourceforge.pmd.cpd.LanguageFactory;
import net.sourceforge.pmd.cpd.Match;
import net.sourceforge.pmd.cpd.Tokenizer;
import org.gradle.api.GradleException;
import org.gradle.workers.WorkAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

    // Visible for testing
    CpdAction(CpdExecutor executor, CpdReporter reporter) {
        this.executor = executor;
        this.reporter = reporter;
    }

    @Override
    public void execute() {
        List<Match> matches = executor.run(createCpdConfiguration(getParameters()), getParameters().getSourceFiles().getFiles());
        reporter.generate(getParameters().getReportParameters().get(), matches);
        logResult(matches);
    }

    private CPDConfiguration createCpdConfiguration(CpdWorkParameters config) {
        CPDConfiguration result = new CPDConfiguration();
        result.setEncoding(config.getEncoding().get());
        result.setLanguage(createLanguage(config.getLanguage().get(), createLanguageProperties(config)));
        result.setMinimumTileSize(config.getMinimumTokenCount().get());
        result.setSkipDuplicates(config.getSkipDuplicateFiles().get());
        result.setSkipLexicalErrors(config.getSkipLexicalErrors().get());
        return result;
    }

    private void logResult(List<Match> matches) {
        if (matches.isEmpty()) {
            if (logger.isInfoEnabled()) {
                logger.info("No duplicates over {} tokens found.", getParameters().getMinimumTokenCount().get());
            }
        } else {
            String message = "CPD found duplicate code.";
            Report report = getParameters().getReportParameters().get().get(0);