1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package Torello.Java;

import Torello.Java.FileNode;

import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.io.IOException;

class InternalSED
{
    static final ResultsSED NO_CHANGES_RET = new ResultsSED(null, 0);

    static class ResultsSED
    {
        final String    newFileAsStr;
        final int       NUM_CHANGED;

        ResultsSED(final String newFileAsStr, final int NUM_CHANGED)
        {
            this.newFileAsStr = newFileAsStr;
            this.NUM_CHANGED  = NUM_CHANGED;
        }
    }

    @FunctionalInterface
    interface FunctionSED
    {
        public ResultsSED apply(
                final String        fileName,
                final FileNode      file,
                final String        fileAsStr,
                final CONFIG_RECORD userConfig
            )
            throws IOException;
    }

    // Only Method
    static List<FileNode> run(
            final Iterable<FileNode>    files,
            final CONFIG_RECORD         userConfig,
            final FunctionSED           handleOneFile
        )
        throws IOException
    {
        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
        // Minor User Error-Check & Initialization
        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

        Helper.CHECK(userConfig.askFirst, userConfig.verbosity);

        // A very short "Consumer" that really just prints the file-name, nothing more.
        final Consumer<String> fileNamePrinter = Helper.getFileNamePrinter
            (userConfig.appendable, userConfig.useUNIXColors, userConfig.verbosity.level);


        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
        // MAIN-LOOP: Iterate all the FileNode's
        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

        for (final FileNode file : files)
        {
            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
            // Print the File Name to the User-Terminal 
            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

            // Load the File
            final String fileName = file.getFullPathName();

            // Print the file-name, if the verbosity level mandates that it be printed
            fileNamePrinter.accept(fileName);


            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
            // Load the File from disk
            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

            final String fileAsStr;

            try
                { fileAsStr = FileRW.loadFileToString(fileName); }
    
            catch (IOException e)
            {
                if (userConfig.ioeh != null)    userConfig.ioeh.accept(file, e);
                else                            throw e;
    
                // if ioeh ignores the exception rather than halting the program, then just
                // continue the loop on to the next match
    
                continue;
            }


            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
            // Run the exact, User-Requested, version of SED-Replacement
            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

            final ResultsSED ret = handleOneFile.apply(fileName, file, fileAsStr, userConfig);

            if (ret.NUM_CHANGED == 0) continue;


            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
            // Write the Replacement, if changes have occured, and the user approved those changes
            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

            try
                { FileRW.writeFile(ret.newFileAsStr, fileName); }

            catch (IOException e)
            {
                if (userConfig.ioeh != null)    userConfig.ioeh.accept(file, e);
                else                            throw e;


                // if ioeh ignores the exception rather than halting the program, then just continue
                // the loop on to the next match

                continue;
            }

            // In "Verbosity.Verbose" mode, tell the user how many changes were updated in the file
            if (userConfig.verbosity.level == 3)
                userConfig.appendable.append(Helper.I4 + "Updated " + ret.NUM_CHANGED + " Matches");

            // This is a file that was updated, so put it in the returned list of "updated files"
            userConfig.ret.accept(file);
        }


        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
        // Finished, so return the list of modified FileNode's
        // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

        return userConfig.ret.build().collect(Collectors.toList());
    }
}