All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ats.gherkin.GherkinTransformer Maven / Gradle / Ivy

The newest version!
package com.ats.gherkin;
import java.io.*;
import java.nio.file.*;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;

import com.github.difflib.DiffUtils;
import com.github.difflib.patch.AbstractDelta;
import com.github.difflib.patch.DeltaType;
import com.github.difflib.patch.Patch;
import com.ats.script.actions.*;
import org.jetbrains.annotations.NotNull;

public class GherkinTransformer {

    public class DiffStruct implements Comparable {
        public enum DiffType {
            ADDED, DELETED, MODIFIED
        }

        private DiffType type;
        private int index;
        private String newContent;
        private String oldContent;

        public DiffStruct(DiffType type, int index, String newContent, String oldContent) {
            this.type = type;
            this.index = index;
            this.newContent = newContent;
            this.oldContent = oldContent;
        }

        public DiffType getType() {
            return type;
        }

        public int getIndex() {
            return index;
        }

        public String getNewContent() {
            return newContent;
        }

        @Override
        public String toString() {
            return "Diff [type=" + type + ", index=" + index + ", newContent=" + newContent + ", oldContent=" + oldContent + "]";
        }

        @Override
        public int compareTo(@NotNull DiffStruct other) {
            int contentComparison = this.newContent.compareTo(other.newContent);
            if (contentComparison != 0) {
                return contentComparison;
            }

            int indexComparison = Integer.compare(this.index, other.index);
            if (indexComparison != 0) {
                return indexComparison;
            }

            return this.type.compareTo(other.type);
        }
        @Override
        public boolean equals(Object other) {
            if (this == other) return true;
            if (other == null || getClass() != other.getClass()) return false;
            DiffStruct that = (DiffStruct) other;
            return index == that.index && type == that.type && Objects.equals(newContent, that.newContent);
        }

        @Override
        public int hashCode() {
            return Objects.hash(type, index, newContent);
        }
    }

    public class ScenarioStruct {
        public String fileName;

        public List lstDiff;

        public ScenarioStruct(String name, List lstDiff) {
            this.fileName = name;
            this.lstDiff = lstDiff;
        }

        public List getAddedDiff() {
            return getDiff(DiffStruct.DiffType.ADDED);
        }

        public List getDeletedDiff() {
            return getDiff(DiffStruct.DiffType.DELETED);
        }

        public List getModifiedDiff() {
            return getDiff(DiffStruct.DiffType.MODIFIED);
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("Scenario [name=").append(fileName).append("\n");

            for (DiffStruct diff : lstDiff) {
                sb.append("   ").append(diff.toString()).append("\n");
            }

            sb.append("]");
            return sb.toString();
        }

        private List getDiff(DiffStruct.DiffType diffType) {
            List addedDiffs = lstDiff.stream()
                    .filter(diff -> diff.getType() == diffType)
                    .collect(Collectors.toList());
            return addedDiffs;
        }

    }

    private Map> transformationMap;
    private String gherkinFilePath;
    private String propertiesFilePath;
    private String projectPath;
    private List atsContent; // List to store content to write later
    final private String dataPath = "src\\assets\\data\\";
    final private String atsFilesPath = "src\\main\\ats\\";

    final private String subStrCmd = "subscript_";

    final private String prefixDataFN = "data_";

    /**
     * Constructor
     * @param projectPath project path for ats and csv files
     * @param gherkinFilePath gherkin file path (.feature)
     * @param propertiesFilePath actions/gherkin association file path (default name: map.properties)
     */
    public GherkinTransformer(String projectPath, String gherkinFilePath, String propertiesFilePath) {
        if (!projectPath.endsWith(File.separator)) {
            this.projectPath = projectPath + File.separator;
        } else {
            this.projectPath = projectPath;
        }
        this.gherkinFilePath = gherkinFilePath;
        this.propertiesFilePath = propertiesFilePath;
        this.transformationMap = readActionFile(propertiesFilePath);
        this.atsContent = new ArrayList<>();
    }

    /**
     * transform gherkin file into ats file
     */
    public void transform() throws IOException, NoSuchAlgorithmException {
        String fileName = null;
        try (BufferedReader reader = new BufferedReader(new FileReader(gherkinFilePath))) {
            String line;
            boolean lastLineWasEmpty = false;
            List examplesHeaders = null;
            List> examplesRows = new ArrayList<>();

            while ((line = reader.readLine()) != null) {
                line = line.trim();

                if (line.startsWith("Scenario") ||
                        line.startsWith("Scenario Outline")) {
                    fileName = setFileNameFromScenario(line);
                }

                if ((line.startsWith("Scenario") ||
                    line.startsWith("Scenario Outline") || 
                    line.startsWith("#Author") || 
                    line.startsWith("#URL")) && 
                    lastLineWasEmpty)                 
                {
                    writeFiles(fileName, examplesHeaders, examplesRows, this.atsContent);
                    atsContent.clear(); // Clear the list for the next scenario

                    examplesHeaders = null;
                    examplesRows.clear();
                }

                lastLineWasEmpty = line.isEmpty();

                if (line.trim().toLowerCase().startsWith("examples:")) { // start of a data block
                    examplesHeaders = new ArrayList<>();
                    String headersLine = reader.readLine().trim();
                    examplesHeaders.addAll(Arrays.asList(headersLine.split("\\|")));
                    examplesHeaders.removeIf(String::isEmpty); // Remove empty elements
                } else if (examplesHeaders != null && line.trim().startsWith("|")) { // line of data
                    List row = new ArrayList<>(Arrays.asList(line.split("\\|")));
                    row.removeIf(String::isEmpty); // Remove empty elements
                    examplesRows.add(row);
                } else if (!line.isEmpty()) {
                    this.atsContent = gherkinToAts(line, this.atsContent);
                }
            }
            writeFiles(fileName, examplesHeaders, examplesRows, this.atsContent);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Updates ats files from gherkin file
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public void applyGherkinChangesToAts() throws IOException, NoSuchAlgorithmException {
        int idx = -1;

        List lstDiffGherkin =  this.compareGherkinToAts();

        // Display
        /*
        for (GherkinTransformer.ScenarioStruct scenario : lstDiffGherkin) {
            if (!scenario.lstDiff.isEmpty()) {
                System.out.println(scenario);
            }
        }
        */

        if (lstDiffGherkin.isEmpty()) return;

        for (ScenarioStruct scenario : lstDiffGherkin) {
            // Lire le contenu du fichier ats
            List> atsLines = readAtsFile(scenario.fileName);

            for (DiffStruct diff : scenario.lstDiff) {
                switch (diff.type) {
                    case MODIFIED:
                        idx = findRowInAts(atsLines, diff.oldContent);
                        if (idx == -1) continue;
                        atsLines.get(idx).set(0, "comment -> " + diff.newContent);
                        //Regenerate actions ?
                        break;

                    case ADDED:
                        List lst = new ArrayList<>(List.of("comment -> " + diff.newContent));
                        lst = gherkinToAts(diff.newContent, lst);
                        atsLines.add(diff.getIndex(), lst);
                        break;
                }
            }
            //Separate deletion so as not to disrupt indexes
            for (DiffStruct diff : scenario.getDeletedDiff()) {
                idx = findRowInAts(atsLines, diff.oldContent);
                if (idx == -1) continue;
                atsLines.remove (idx);
            }

            // Transform List> into List
            List flatList = atsLines.stream()
                    .flatMap(List::stream)
                    .collect(Collectors.toList());

            //Save file
            Files.write(Paths.get(scenario.fileName), flatList);
        }
    }

    /**
     * Deletes ats and csv files in the outputFilePath
     */
    public void deleteAtsAndCsvFiles() {
        deleteFiles(this.projectPath + this.atsFilesPath, ".ats");
        deleteFiles(this.projectPath + this.dataPath, ".csv");
    }

    /*******************************/
    /*      PRIVATE FUNCTIONS      */
    /*******************************/

    /**
     * get an gherkin line, return ats action
     * @param line gherkin line
     * @param atsContent list of ats command
     * @return enriched ats list
     */
    private List gherkinToAts(String line, List atsContent) {
        //Exclude data rows
        if (line.trim().toLowerCase().startsWith("examples")
                || line.trim().toLowerCase().startsWith("|")) {
            return atsContent;
        }

        String subscript = "subscript"; // Pourrait être initialisé avec projet.app.lib trouvé quelque par dans le script

        atsContent.add("comment -> " + line);

        for (Map.Entry> entry : transformationMap.entrySet()) {
            for (String phrase : entry.getValue()) {
                if (line.toLowerCase().contains(phrase.toLowerCase())) {
                    switch (entry.getKey()) {
                        case "ActionGotoUrl":
                            atsContent.add(ActionGotoUrl.getAtsCodeStr(subscript,"google.com").toString());
                            break;
                        case "ActionText":
                            atsContent.add(ActionText.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionAssertValue":
                            atsContent.add(ActionAssertValue.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionClick":
                            atsContent.add(ActionMouse.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionAssertCount":
                            atsContent.add(ActionAssertCount.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionAssertProperty":
                            atsContent.add(ActionAssertProperty.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionButton":
                            atsContent.add(ActionButton.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionCallscript":
                            atsContent.add(ActionCallscript.getAtsCodeStr().toString());
                            break;
                        case "ActionChannel":
                            atsContent.add(ActionChannel.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionChannelClose":
                            atsContent.add(ActionChannelClose.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionChannelExist":
                            atsContent.add(ActionChannelExist.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionChannelStart":
                            atsContent.add(ActionChannelStart.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionChannelSwitch":
                            atsContent.add(ActionChannelSwitch.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionMouseScroll":
                            atsContent.add(ActionMouseScroll.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionSelect":
                            atsContent.add(ActionSelect.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionWindow":
                            atsContent.add(ActionWindow.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionWindowResize":
                            atsContent.add(ActionWindowResize.getAtsCodeStr(subscript).toString());
                            break;
                        case "ActionWindowState":
                            atsContent.add(ActionWindowState.getAtsCodeStr(subscript).toString());
                            break;

                        default:
                            break;
                    }
                    break;
                }
            }
        }
        return atsContent;
    }

    /**
     * Function to compare files and find additions, deletions and modifications
     * Compare Gherkin file with ats comments
     * @return Structured list of différences
     */
    private List compareGherkinToAts() throws IOException, NoSuchAlgorithmException {
        // Reading the Gherkin file by scenario
        List> gherkinLst = this.splitFileByConditions(this.gherkinFilePath);

        // Create a list to remember the differences
        List diffLst = new ArrayList<>(gherkinLst.size());

        for (int i = 0; i < gherkinLst.size(); i++)
        {
            String atsFileName = searchAtsFileName(gherkinLst.get(i));
            if (atsFileName != null) {
                String fileName;

                atsFileName = setFileNameFromScenario(atsFileName) + ".ats";
                // Test if the subscript exists
                if (this.fileExistsInDirectory(this.projectPath + this.atsFilesPath, this.subStrCmd + atsFileName)) {
                    fileName = this.projectPath + this.atsFilesPath + this.subStrCmd + atsFileName;
                } else {
                    fileName = this.projectPath + this.atsFilesPath + atsFileName;
                }

                if (!this.fileExistsInDirectory(this.projectPath + this.atsFilesPath, atsFileName)) {
                    createNewScenario(gherkinLst.get(i));
                    continue;
                }

                List lstAtsComment = extractComments(fileName);
                List subGherkinLst = gherkinLst.get(i);

                /* AFFICHAGE DES LISTES A COMPARER */
                /*
                System.out.println("");
                System.out.println("Fichier ats");
                for (String line : lstAtsComment) {
                    System.out.println("'" + line + "'");
                }
                System.out.println("");
                System.out.println("Fichier Gherkin");
                for (String line : separatedLists.get(i)) {
                    System.out.println("'" + line + "'");
                }
                */
                removeDataFromScenario(subGherkinLst);
                List subDiffLst = compareGherkinToAts(subGherkinLst, lstAtsComment, new ArrayList<>());
                // second pass without changes to spot deleted or added lines

                subDiffLst = compareGherkinToAts(subGherkinLst, lstAtsComment, subDiffLst);

                if (!subDiffLst.isEmpty()) {
                    diffLst.add(new ScenarioStruct(fileName, subDiffLst));
                }
            }
        }

        return diffLst;
    }

    /**
     * Create new scenario
     * @param gherkinScenario
     * @throws IOException
     */
    private void createNewScenario(List gherkinScenario) throws IOException {
        String fileName = null;
        List examplesHeaders = new ArrayList<>();
        List> examplesRows = new ArrayList<>();
        List atsContent = new ArrayList<>();

        boolean firstDataLine = true;
        for (String gherkinStr: gherkinScenario) {
            // get scenario name -> filename
            if (gherkinStr.startsWith("Scenario") ||
                    gherkinStr.startsWith("Scenario Outline")) {
                fileName = setFileNameFromScenario(gherkinStr);
            }

            //Read data
            if (gherkinStr.trim().startsWith("|")) { // line of data
                if (firstDataLine) {
                    examplesHeaders = new ArrayList<>();
                    examplesHeaders.addAll(Arrays.asList(gherkinStr.split("\\|")));
                    examplesHeaders.removeIf(String::isEmpty); // Remove empty elements
                    firstDataLine = false;
                } else {
                    List row = new ArrayList<>(Arrays.asList(gherkinStr.split("\\|")));
                    row.removeIf(String::isEmpty); // Remove empty elements
                    examplesRows.add(row);
                }
            }

            atsContent = gherkinToAts(gherkinStr, atsContent);
        }

        if (fileName != null) {
            this.writeFiles(fileName, examplesHeaders, examplesRows, atsContent);
        }
    }

    /**
     * Compare Gherkin and ats scenario
     * @param gherkinScenario Gherkin scenario
     * @param lstAtsComment Ats comments scenario
     * @param subDiffLst Work list
     * @return List of différences
     * @throws NoSuchAlgorithmException
     */
    private List compareGherkinToAts(List gherkinScenario, List lstAtsComment, List subDiffLst) throws NoSuchAlgorithmException {
        // Compare the two lists with DiffUtils
        Patch patch = DiffUtils.diff(lstAtsComment, gherkinScenario);
        // Browse and view differences
        for (AbstractDelta delta : patch.getDeltas()) {
            if (delta.getType() == DeltaType.INSERT) {
                List addedLines = delta.getTarget().getLines();
                for (int j = 0; j < addedLines.size(); j++) {
                    int addedIndex = delta.getTarget().getPosition() + j;
                    if (!subDiffLst.stream().anyMatch(diff -> diff.getIndex() == addedIndex && diff.getType() == DiffStruct.DiffType.ADDED))
                    {
                        subDiffLst.add(new DiffStruct(DiffStruct.DiffType.ADDED, addedIndex, addedLines.get(j), ""));
                    }
                }
            } else if (delta.getType() == DeltaType.DELETE) {
                // System.out.println(delta.getSource());
                List deletedLines = delta.getSource().getLines();
                for (int j = 0; j < deletedLines.size(); j++) {
                    int deletedIndex =  delta.getSource().getPosition() + j;  // Index in the base file
                    // "Ligne supprimée (index " + deletedIndex + ") : " + deletedLines.get(j);
                    DiffStruct line = new DiffStruct(DiffStruct.DiffType.DELETED, deletedIndex, "", deletedLines.get(j));
                    if (!subDiffLst.contains(line)) {
                        subDiffLst.add(line);
                    }
                }
            } else if (delta.getType() == DeltaType.CHANGE) {
                // System.out.println(delta.getSource());
                List originalLines = delta.getSource().getLines();
                List revisedLines = delta.getTarget().getLines();
                for (int j = 0; j < originalLines.size(); j++) {
                    int originalIndex = delta.getSource().getPosition() + j;  // Index in the base file
                    int revisedIndex = delta.getTarget().getPosition() + j;   // Index in the modified file
                    if (j < revisedLines.size()) {
                        int levenDist = this.calculateLevenshteinDistance(originalLines.get(j), revisedLines.get(j));
                        // System.out.println("Levenshtein Distance : " + levenDist);
                        DiffStruct line1;
                        DiffStruct line2;
                        if (levenDist > 40) {
                            line1 = new DiffStruct(DiffStruct.DiffType.DELETED, originalIndex, "", originalLines.get(j));
                            line2 = new DiffStruct(DiffStruct.DiffType.ADDED, revisedIndex, revisedLines.get(j) ,"");
                            subDiffLst.add(line1);
                            subDiffLst.add(line2);
                        } else {
                            subDiffLst.add(new DiffStruct(DiffStruct.DiffType.MODIFIED, revisedIndex, revisedLines.get(j), originalLines.get(j)));
                        }

                        lstAtsComment.set(originalIndex, revisedLines.get(j));
                    } else {
                        //The line has actually been deleted
                        // "Ligne supprimée (index " + originalIndex + ") : " + originalLines.get(j);
                        subDiffLst.add(new DiffStruct(DiffStruct.DiffType.DELETED, originalIndex, "", originalLines.get(j)));
                    }
                }
            }
        }
        return subDiffLst;
    }

    /**
     * Read the ats file and render it as a list of lists, the first element of the sublists is the comment from gherkin, the rest are the actions
     * @param filePath
     * @return a list of lists, the first element of the sublists is the comment from gherkin, the rest are the actions
     * @throws IOException
     */
    private List> readAtsFile(String filePath) throws IOException {
        List lines = Files.readAllLines(Paths.get(filePath));
        List> atsFile = new ArrayList<>();
        List lst = null;

        for (String line : lines) {
            if (line.trim().startsWith("comment ->")) {
                if (lst != null) {
                    atsFile.add(lst);
                }
                lst = new ArrayList<>();
            }
            lst.add(line.trim());
        }
        if (lst != null) {
            atsFile.add(lst);
        }
        return atsFile;
    }

    /**
     * search for scenario name in gherkin scenario
     * @param lstScenario gherkin scenario as list, no empty lines
     * @return the name of the scenario
     */
    private String searchAtsFileName(List lstScenario) {
        Optional result = lstScenario
                .stream()
                .map(String::trim)
                .filter(element -> element.startsWith("Scenario"))
                .findFirst();

        if (result.isPresent()) {
            return result.get();
        } else {
            return null;
        }
    }

    /**
     * Delete files from a directory based on their extension
     * @param path
     * @param extension
     */
    private void deleteFiles(String path, String extension) {
        File directory = new File(path);
        if (directory.exists() && directory.isDirectory()) {
            File[] files = directory.listFiles((dir, name) -> name.endsWith(""));
            if (files != null) {
                for (File file : files) {
                    file.delete();
                }
            }
        }
    }

    /**
     * Write ats and csv files
     * @param dataHeaders data header
     * @param dataRows data rows
     * @throws IOException
     */
    private void writeFiles(String fileName, List dataHeaders, List> dataRows, List atsContent) throws IOException {
        if (fileName == null) return;

        if (!atsContent.isEmpty()) {
            String filename = fileName + ".ats";
            String dataFilename = prefixDataFN + fileName + ".csv";

            if (dataHeaders != null && !dataRows.isEmpty()) {
                writeAtsBaseFile(filename, dataFilename);
                writeAtsFile(this.projectPath + this.atsFilesPath + subStrCmd + filename, atsContent);
                writeExamplesToCsv(this.projectPath + this.dataPath + dataFilename, dataHeaders, dataRows);
            } else {
                writeAtsFile(this.projectPath + this.atsFilesPath + filename, atsContent); // Write accumulated content to .ats file after last scenario
            }
        }
    }

    /**
     * Write ats file
     * @param outputFilePath
     * @throws IOException
     */
    private void writeAtsFile(String outputFilePath, List atsContent) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputFilePath))) {
            for (String line : atsContent) {
                writer.write(line);
                writer.newLine();
            }
        }
    }

    /**
     * Created the ats file which calls the sub script
     * @param atsFileName
     * @param dataFileName file name without path
     * @throws IOException
     */
    private void writeAtsBaseFile(String atsFileName, String dataFileName) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(this.projectPath + this.atsFilesPath + atsFileName))) {
                writer.write("callscript -> " + subStrCmd + atsFileName + " -> assets:///data/" + dataFileName);
                writer.newLine();
        }
    }

    /**
     * read the file that contains the action/gherkin code association
     *
     * @param filePath The path to the file containing the actions and associated sentences
     * @return A map where each key is an action and the associated value is a list of sentences
     */
    private Map> readActionFile(String filePath) {
        Map> transformationMap = new HashMap<>();
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.trim().isEmpty() || line.trim().startsWith("#")) {
                    continue;
                }
                String[] parts = line.split("=", 2);
                if (parts.length == 2) {
                    String action = parts[0].trim();
                    String[] phrases = parts[1].split("\\|");
                    List phraseList = new ArrayList<>();
                    for (String phrase : phrases) {
                        phraseList.add(phrase.trim());
                    }
                    transformationMap.put(action, phraseList);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return transformationMap;
    }

    /**
     *  Write csv file
     * @param fileName csv file name with path
     * @param dataHeaders data file header
     * @param dataRows datafile data
     */
    private void writeExamplesToCsv(String fileName, List dataHeaders, List> dataRows) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
            // Surround each element of examplesHeaders with <>
            List formattedHeaders = new ArrayList<>();
            for (String header : dataHeaders) {
                formattedHeaders.add("<" + header.trim() + ">");
            }
    
            // Write the header
            writer.write(String.join(",", formattedHeaders));
            writer.newLine();
    
            // Write the data lines
            for (List row : dataRows) {
                writer.write(String.join(",", row));
                writer.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Set the file name without extension from the scenario line
     * @param scenarioName Name of the scenario
     */
    private String setFileNameFromScenario(String scenarioName) {
        String filename = (scenarioName.substring(scenarioName.indexOf(":") + 1).trim());
        filename = filename.replace(" ", "_");
        return filename;
    }

    /**
     * Read the gherkin file for comparison
     * @param filePath path of the gherkin file
     * @return List of scenario
     * @throws IOException
     */
    public static List> splitFileByConditions(String filePath) throws IOException {
        List lines = Files.readAllLines(Paths.get(filePath));
        List> separatedLists = new ArrayList<>();
        List currentList = new ArrayList<>();
        boolean lastLineWasEmpty = true; // Initialize as true to capture the first block

        for (String line : lines) {
            // Check if the line is empty
            if (line.trim().isEmpty()) {
                lastLineWasEmpty = true;  // Mark that the last line was empty
            } else {
                // If the condition is met and the last line was empty, a new sublist is started
                if ((line.startsWith("Scenario") ||
                        line.startsWith("Scenario Outline") ||
                        line.startsWith("#Author") ||
                        line.startsWith("#URL")) &&
                        lastLineWasEmpty) {

                    // Add the current list to the main list if it is not empty
                    if (!currentList.isEmpty()) {
                        separatedLists.add(currentList);
                    }
                    // Start a new sublist
                    currentList = new ArrayList<>();
                }
                //if (!line.trim().startsWith("Examples") && !line.trim().startsWith("|")) { //Exclude data
                    currentList.add(line.trim());
                //}
                lastLineWasEmpty = false;
            }
        }

        // Add the last sublist after the loop if it is not empty
        if (!currentList.isEmpty()) {
            separatedLists.add(currentList);
        }

        return separatedLists;
    }

    /**
     * Search if a file exists in a directory
     * @param directoryPath
     * @param fileName
     * @return
     */
    public boolean fileExistsInDirectory(String directoryPath, String fileName) {
        Path filePath = Paths.get(directoryPath, fileName);
        return Files.exists(filePath);
    }

    /**
     * Calculate the Levenshtein distance between two String
     * @param str1
     * @param str2
     * @return The distance
     */
    public int calculateLevenshteinDistance(String str1, String str2) {
        int[][] dp = new int[str1.length() + 1][str2.length() + 1];

        // Remplir la première colonne et la première ligne
        for (int i = 0; i <= str1.length(); i++) {
            dp[i][0] = i;
        }
        for (int j = 0; j <= str2.length(); j++) {
            dp[0][j] = j;
        }

        // Remplir la matrice dp
        for (int i = 1; i <= str1.length(); i++) {
            for (int j = 1; j <= str2.length(); j++) {
                int cost = (str1.charAt(i - 1) == str2.charAt(j - 1)) ? 0 : 1;
                dp[i][j] = Math.min(
                        Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1),
                        dp[i - 1][j - 1] + cost
                );
            }
        }

        return dp[str1.length()][str2.length()];
    }

    /**
     * remove data from gherkin scenario
     * @param list scenario
     */
    private static void removeDataFromScenario(List list) {
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).trim().toLowerCase().startsWith("examples") || list.get(i).trim().toLowerCase().startsWith("|")) {
                list.subList(i, list.size()).clear();
                break;
            }
        }
    }

    /**
     * search for a comment in the ats file
     * @param atsLines the ats file
     * @param toFind the chain to find without the "comment ->"
     * @return
     */
    private int findRowInAts(List> atsLines, String toFind) {
        for (int i = 0; i < atsLines.size(); i++) {
            String atsLine = atsLines.get(i).get(0);
            if (atsLine.startsWith("comment -> ")) {
                String lineWithoutPrefix = atsLine.substring("comment -> ".length());
                if (lineWithoutPrefix.equals(toFind)) {
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * Function to extract comments from ats file for comparison
     * @param filePath Path to ats file
     * @return atsfile comments list
     * @throws IOException
     */
    private List extractComments(String filePath) throws IOException {
        List lines = Files.readAllLines(Paths.get(filePath));
        List comments = new ArrayList<>();

        for (String line : lines) {
            if (line.trim().startsWith("comment ->")) {
                comments.add(line.substring(10).trim());  // Ajouter à la liste des commentaires
            }
        }

        return comments;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy