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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | package Torello.Java; import Torello.Java.Additional.AppendableSafe; import Torello.Java.Additional.BiAppendable; import static Torello.Java.C.BGREEN; import static Torello.Java.C.RESET; import java.util.regex.Pattern; import java.util.regex.MatchResult; import java.util.function.Function; import java.util.stream.Stream; // This Configuration-Record is generated solely from the User-Input Method-Parameters which may be // passed to the 8 variants that are offered by the Top-Level User-API Class 'SED'. This // Data-Record Class does not have any methods whatsoever - it only has constructors. Furthermore // the fields in this Data-Class are fields which are strictly obtained (directly copied) from the // User-Input Parameters obtained from the eight methods offered by class 'Torello.Java.SED' // // ================================================================================================ // // The biggest benefit of looking at this is that *EVERY SINGLE ONE* of the following fields are // all declared 'final', and that means that when looking at the code inside of the various classes // which do the processing for this Top-Level Dispatch-Class (Torello.Java.SED) you should be ssafe // in knowing that instances of this class are strictly Data-Lookup, and therefore do not contain // any fields which may be modified during the processing of a Text-File. For some programmers, // especially me, this can be a somewhat non-trivial value when trying to understand what the hell // these complicated for-loops and string-processing methods are even doing. // // Note that this class has two variants for constructors. One of the constructors is used for // SED-Replacement that involves Regular-Expressions, while the latter is used for direct // String-to-String replacements // // Constructor-Variant ONE Parameters: // final String matchStr // final String replaceStr // // Constructor-Variant TWO Parameters: // final Pattern regEx, // final Function<MatchResult, String> replaceFunction // // ================================================================================================ // // The second biggest benefit that this class provides is that because all of these fields are used // sporadically throught he processing classes, it is more efficient to pass the parameters around // the internal methods used by SED. Passing one single Record that contains all of the // Data-Fields (obtained from user parameters) to the methods means that their are fewer parameters // or "arguments" to the various methods in SED. class CONFIG_RECORD { // ******************************************************************************************** // ******************************************************************************************** // The two Data-Records // ******************************************************************************************** // ******************************************************************************************** // These two fields are only used when the User is doing a **REGULAR-EXPRESSION** Replacement final Pattern regEx; final Function<MatchResult, String> replaceFunction; // These two fields are only used when the User is doing a **STRING** Replacement final String matchStr; final String replaceStr; // This value is used repeatedly in this loop, so it is better left as a constant final int MATCH_STR_LEN; // These five fields are used when either of the two variants of SED are invoked final boolean askFirst; final IOExceptionHandler ioeh; final boolean useUNIXColors; final Verbosity verbosity; final Appendable appendable; // Simple Print Loop Helpers ... final String HILITE_START; final String HILITE_END; // This Stream-Builder contains the list of FileNode's that are modified. This Stream-Builder // generates the Returned-Value from all of the SED methods which are offered by the Top-Level // User-API SED-Class. final Stream.Builder<FileNode> ret = Stream.builder(); // ******************************************************************************************** // ******************************************************************************************** // Two Constructors: One for the two Regular-Expression SED Methods, and one for String-Repl... // ******************************************************************************************** // ******************************************************************************************** // This Constructor is invoked by the two public SED methods which accept a Regular-Expression // Matcher along with a MatchResult Replacement-Function CONFIG_RECORD( final Pattern regEx, final Function<MatchResult, String> replaceFunction, final boolean askFirst, final IOExceptionHandler ioeh, final boolean useUNIXColors, final Verbosity verbosity, final Appendable outputSaver ) { this.regEx = regEx; this.replaceFunction = replaceFunction; this.matchStr = null; this.replaceStr = null; this.MATCH_STR_LEN = -1; this.askFirst = askFirst; this.ioeh = ioeh; this.useUNIXColors = useUNIXColors; this.verbosity = verbosity; this.appendable = generateTheAppendable(outputSaver); this.HILITE_START = useUNIXColors ? BGREEN : ""; this.HILITE_END = useUNIXColors ? RESET : ""; } // This Constructor is (obviously!) invoked by the two SED methods which accept a Match-Sring // and a Replacement-String as Configuration-Parameters. CONFIG_RECORD( final String matchStr, final String replaceStr, final boolean askFirst, final IOExceptionHandler ioeh, final boolean useUNIXColors, final Verbosity verbosity, final Appendable outputSaver ) { this.regEx = null; this.replaceFunction = null; this.matchStr = matchStr; this.replaceStr = replaceStr; this.MATCH_STR_LEN = matchStr.length(); this.askFirst = askFirst; this.ioeh = ioeh; this.useUNIXColors = useUNIXColors; this.verbosity = verbosity; this.appendable = generateTheAppendable(outputSaver); this.HILITE_START = useUNIXColors ? BGREEN : ""; this.HILITE_END = useUNIXColors ? RESET : ""; } // ******************************************************************************************** // ******************************************************************************************** // Very Short, Static, Constructor-Helper Method // ******************************************************************************************** // ******************************************************************************************** private static Appendable generateTheAppendable(final Appendable outputSaver) { return (outputSaver == null) // If no 'outputSaver' was provided, then just send text to Standard-Out ? System.out // This just allows for printing to **BOTH** System.out **AND** the 'outputSaver' : new BiAppendable (System.out, new AppendableSafe(outputSaver, AppendableSafe.USE_APPENDABLE_ERROR)); } } |