001package Torello.Java;
002
003import Torello.Java.Function.ToCharIntCharFunc;
004import Torello.Java.Function.IntCharFunction;
005import Torello.Java.Function.ToCharIntTFunc;
006import Torello.Java.Function.IntTFunction;
007
008import Torello.JavaDoc.LinkJavaSource;
009import static Torello.JavaDoc.Entity.METHOD;
010
011/**
012 * An efficient way to replace multiple substring's, or single-characters, inside of a single
013 * Java String, <I>in place, without rebuilding the returned {@code String} more than once.</I>
014 * 
015 * <EMBED CLASS=external-html DATA-FILE-ID=STR_REPLACE>
016 */
017@Torello.JavaDoc.StaticFunctional
018public class StrReplace
019{
020    private StrReplace() { }
021
022    /**
023     * Convenience Method.
024     * <BR />Case-Sensitive
025     * <BR />See Documentation: {@link #r(boolean, String, String[], String[])}
026     */
027    @LinkJavaSource(handle="StrArrToStrArr")
028    public static String r(String s, String[] matchStrs, String[] replaceStrs)
029    { return StrArrToStrArr.replace(false, s, matchStrs, replaceStrs); }
030
031    /**
032     * This shall replace each instance of the elements of parameter {@code 'matchStrs'} in input
033     * {@code String 's'} with the elements of <I><B>parallel array</I></B> {@code 'replaceStrs'}
034     *
035     * @param ignoreCase When this parameter is set to {@code TRUE}, then the comparisons that
036     * determine whether a match has occurred shall ignore the case of the characters involved.
037     * 
038     * @param s This may be any Java {@code String}.
039     * 
040     * @param matchStrs This is a {@code String[] array} that should hold some sub-strings of input
041     * parameter {@code 's'}.  This method shall search {@code 's'} - <I>left to right</I> - for
042     * any instances of the list of {@code 'matchStrs'} and replace those sub-strings with 
043     * whatever {@code String} is in the <I>same array-index location (parallel-array)</I> from
044     * input parameter {@code 'replaceStrs'}
045     * 
046     * <BR /><BR /><DIV CLASS=JDHint>
047     * <B STYLE="color: red;">Multiple-Match Scenarious:</B> If there are substring's
048     * within parameter {@code 'matchStrs'} such that the loop-iterations of this method could
049     * select multiple, different {@code String's} as a substring match with the input parameter
050     * {@code 's'}, then the loops will <I><B>always replace the first match found with input
051     * {@code String[] array} parameter {@code 'matchStrs'}</I></B>.
052     * </DIV>
053     * 
054     * <DIV CLASS=EXAMPLE>{@code
055     * String[] matches         = { "Bell", "Belle", "Belleview" };
056     * String[] replacements    = { "Ring", "Flower", "Microsoft Corporate HQ" };
057     * String   theString       = "Microsoft Corporate Apartments are in Belleview, Washington";
058     *
059     * System.out.println(StrReplace.r(false, theString, matches, replacements));
060     *
061     * // Would print to terminal:
062     * // Microsoft Corporate Apartments are in Ringeview, Washington
063     * 
064     * // This is because the point when the "Replace Loop" cursor reaches character 'B' in
065     * // 'Bellview', the first match it finds with parameter 'matches' is the String "Bell"
066     * // ... And because the 'replacements' parameter maps the word "Bell" to "Ring"
067     * }</DIV>
068     * 
069     * @param replaceStrs This is also an {@code String[] array} that should hold sub-strings.
070     * Every time a copy of any {@code 'matchStr'} is found within {@code 's'}, the index of the
071     * sub-string match from {@code 'matchStrs'} shall be used to lookup the parallel
072     * {@code 'replaceStr'}, and used to over-write or replace that sub-string inside {@code 's'}.
073     * 
074     * <BR /><BR /><DIV CLASS=JDHint>
075     * <B STYLE="color: red;">Parallel Array:</B> This array should be considered parallel to input
076     * {@code String[] array 'matchStrs'}.  It provides a replacement mapping.  It is required to
077     * be the exact same length as array {@code 'matchStrs'}, or an exception shall throw.
078     * </DIV>
079     * 
080     * @return This shall return a new-{@code String} where the replacements that were requested
081     * have been substituted.
082     * 
083     * @throws NullPointerException If any of the {@code String's} inside the {@code String[]
084     * arrays} contain null pointers.
085     * 
086     * @throws ParallelArrayException If the length of array {@code matchStrs} does not equal
087     * the length of array {@code replaceStrs}, then this exception shall throw.   This is because
088     * these arrays are intended to be parallel arrays, where the references in the second array
089     * are supposed to be used to replace sub-strings (in {@code 's'}) from the first array.
090     */
091    @LinkJavaSource(handle="StrArrToStrArr")
092    public static String r(
093            boolean     ignoreCase,
094            String      s,
095            String[]    matchStrs,
096            String[]    replaceStrs
097        )
098    { return StrArrToStrArr.replace(ignoreCase, s, matchStrs, replaceStrs); }
099
100    /**
101     * Convenience Method.
102     * <BR />Case-Sensitive
103     * <BR />See Documentation: {@link #r(boolean, String, String[], IntTFunction)}
104     */
105    @LinkJavaSource(handle="StrArrToReplFunc")
106    public static String r(
107        String s, String[] matchStrs, IntTFunction<String, String> replaceFunction)
108    { return StrArrToReplFunc.replace(false, s, matchStrs, replaceFunction); }
109
110    /**
111     * This shall replace each instance of the elements of parameter {@code 'matchStrs'} in input
112     * {@code String 's'} with the {@code String}-value returned by the {@code 'replaceFunction'}
113     * lambda-method / {@code functional-interface}.
114     * 
115     * @param ignoreCase When this parameter is set to {@code TRUE}, then the comparisons that
116     * determine whether a match has occurred shall ignore the case of the characters involved.
117     * 
118     * @param s This may be any Java {@code String}.
119     * 
120     * @param matchStrs This is an {@code String[] array} that should hold some sub-strings of input
121     * parameter {@code 's'}.  This method shall search {@code 's'} - <I>left to right</I> - for
122     * any instances of the list of {@code 'matchStrs'} and replace those sub-strings with 
123     * whatever {@code String} is returned by the {@code 'replaceFunction'}.
124     * 
125     * <BR /><BR /><DIV CLASS=JDHint>
126     * <B STYLE="color: red;">Multiple-Match Scenarious:</B> If there are substring's
127     * within parameter {@code 'matchStrs'} such that the loop-iterations of this method could
128     * select multiple, different {@code String's} as a substring match with the input parameter
129     * {@code 's'}, then the loops will <I><B>always replace the first match found with input
130     * {@code String[] array} parameter {@code 'matchStrs'}</I></B>.
131     * </DIV>
132     * 
133     * <DIV CLASS="EXAMPLE">{@code
134     * String[] matches         = { "Bell", "Belle", "Belleview" };
135     * String   theString       = "Microsoft Corporate Apartments are in Belleview, Washington";
136     *
137     * System.out.println
138     *     (StrReplace.r(false, theString, matches, (int i, String s) -> s.toUpperCase()));
139     *
140     * // Would print to terminal:
141     * // Microsoft Corporate Apartments are in BELLeview, Washington
142     * 
143     * // This is because the point when the "Replace Loop" cursor reaches character 'B' in
144     * // 'Bellview', the first match it finds with parameter 'matches' is the String "Bell"
145     * // ... And because the 'replaceFunction' parameter merely asks the match-String be
146     * //     converted to upper-case.
147     * }</DIV>
148     * 
149     * @param replaceFunction This shall receive as input a Java {@code String} that has matched
150     * one of the {@code String's} that are within {@code 'matchStrs'}, along with the
151     * {@code String}-index into the {@code String} where that match occured.  It must reply with
152     * a replacement {@code String} (to replace that sub-string within the input {@code String}
153     * parameter {@code 's'})  
154     * 
155     * <EMBED CLASS='external-html' DATA-IN=String DATA-OUT=String
156     *      DATA-FILE-ID=STR_REPLACE_LOOK_AR>
157     * 
158     * @return This shall return a new-{@code String} where the replacements that were requested
159     * have been substituted.
160     * 
161     * @throws NullPointerException If any of the {@code String's} inside the {@code String[]
162     * arrays} contain null pointers.
163     */
164    @LinkJavaSource(handle="StrArrToReplFunc")
165    public static String r(
166            boolean                         ignoreCase,
167            String                          s,
168            String[]                        matchStrs,
169            IntTFunction<String, String>    replaceFunction
170        )
171    { return StrArrToReplFunc.replace(ignoreCase, s, matchStrs, replaceFunction); }
172
173    /**
174     * Convenience Method.
175     * <BR />Case-Sensitive
176     * <BR />See Documentation: {@link #r(String, boolean, String[], ToCharIntTFunc)}
177     */
178    @LinkJavaSource(handle="StrArrToCharReplFunc")
179    public static String r
180        (String s, ToCharIntTFunc<String> replaceFunction, String[] matchStrs)
181    { return StrArrToCharReplFunc.replace(s, false, matchStrs, replaceFunction); }
182
183    /**
184     * This shall replace each instance of the elements of parameter {@code 'matchStrs'} in input
185     * {@code String 's'} with the {@code char}-value returned by the {@code 'replaceFunction'}
186     * lambda-method / {@code functional-interface}.
187     * 
188     * <DIV CLASS="EXAMPLE">{@code
189     * String[] matches    = { "&Pi;", "&Rho;", "&Sigma;", "&Tau;", "&Upsilon;", "&Phi;" };
190     * String   theString  = "Greek: &Pi;, &Rho;, &Sigma;, &Tau;, &Upsilon;, &Phi;";
191     * 
192     * System.out.println
193     *     (StrReplace.r(theString, false, matches, (int i, String s) -> Escape.escHTMLToChar(s)));
194     *
195     * // Would print to terminal:
196     * // Greek: Π, Ρ, Σ, Τ, Υ, Φ 
197     * }</DIV>
198     * 
199     * @param s This may be any Java {@code String}.
200     * 
201     * @param ignoreCase When this parameter is set to {@code TRUE}, then the comparisons that
202     * determine whether a match has occurred shall ignore the case of the characters involved.
203     * 
204     * @param matchStrs This is an {@code String[] array} that should hold some sub-strings of input
205     * parameter {@code 's'}.  This method shall search {@code 's'} - <I>left to right</I> - for
206     * any instances of the list of {@code 'matchStrs'} and replace those sub-strings with 
207     * whatever {@code char} is returned by the {@code 'replaceFunction'} for that given 
208     * match-{@code String};
209     * 
210     * <BR /><BR /><DIV CLASS=JDHint>
211     * <B STYLE="color: red;">Multiple-Match Scenarious:</B> If there are multiple copies (either
212     * ignoring case, or not ignoring case), of an identical {@code String} put into
213     * {@code String[]} array parameter {@code 'matchStrs'}, this method will not generate an
214     * exception (or anything like that) in such scenarios.
215     * </DIV>
216     * 
217     * <BR />It is important to note that when invoking the {@code replaceFunction's} method
218     * {@code apply(String)}, the {@code String} that is provided to {@code apply} will be the
219     * <I>exact substring</I> found in the original-{@code String}.
220     * 
221     * @param replaceFunction This shall receive as input a Java {@code String} that has matched
222     * one of the {@code String's} that are within {@code 'matchStrs'}, along with the
223     * {@code String}-index into the {@code String} where that match occured.  It must reply with
224     * a replacement {@code 'char'} (which will replace that matched sub-string found within 
225     * {@code 's'}).
226     * 
227     * <EMBED CLASS='external-html' DATA-IN=String DATA-OUT=char
228     *      DATA-FILE-ID=STR_REPLACE_LOOK_AR>
229     * 
230     * @return This shall return a new-{@code String} where the replacements that were requested
231     * have been substituted.
232     * 
233     * @throws NullPointerException If any of the {@code String's} inside the {@code String[]
234     * arrays} contain null pointers.
235     */
236    @LinkJavaSource(handle="StrArrToCharReplFunc")
237    public static String r(
238            String                  s,
239            boolean                 ignoreCase,
240            String[]                matchStrs,
241            ToCharIntTFunc<String>  replaceFunction
242        )
243    { return StrArrToCharReplFunc.replace(s, ignoreCase, matchStrs, replaceFunction); }
244
245    /**
246     * Convenience Method.
247     * <BR />Case-Sensitive
248     * <BR />See Documentation: {@link #r(boolean, String, String[], char[])}
249     */
250    @LinkJavaSource(handle="StrArrToCharArr")
251    public static String r(String s, String[] matchStrs, char[] replaceChars)
252    { return StrArrToCharArr.replace(false, s, matchStrs, replaceChars); }
253
254    /**
255     * This shall replace each instance of the elements of parameter {@code 'matchStrs'} in input
256     * {@code String 's'} with the provided characters in <I><B>parallel array</I></B>
257     * {@code 'replaceChars'}.
258     *
259     * <DIV CLASS="EXAMPLE">{@code
260     * String[]  matches       = { "&Pi;", "&Rho;", "&Sigma;", "&Tau;", "&Upsilon;", "&Phi;" };
261     * char[]    replacements  = { 'Π', 'Ρ', 'Σ', 'Τ', 'Υ', 'Φ'  };
262     * String    theString     = "Greek Letters: &Pi;, &Rho;, &Sigma;, &Tau;, &Upsilon;, &Phi;";
263     * 
264     * System.out.println(StrReplace.r(false, theString, matches, replacements);
265     *
266     * // Would print to terminal the following String:
267     * // Greek Letters: Π, Ρ, Σ, Τ, Υ, Φ 
268     * }</DIV>
269     * 
270     * @param s This may be any Java {@code String}.
271     * 
272     * @param ignoreCase When this parameter is set to {@code TRUE}, then the comparisons that
273     * determine whether a match has occurred shall ignore the case of the characters involved.
274     * 
275     * @param matchStrs This is a {@code String[] array} that should hold some sub-strings of input
276     * parameter {@code 's'}.  This method shall search {@code 's'} - <I>left to right</I> - for
277     * any instances of the list of {@code 'matchStrs'} and replace those sub-strings with 
278     * whatever {@code char} is in the <I>same array-index location (parallel-array)</I> from
279     * input parameter {@code 'replaceChars'}.
280     * 
281     * <BR /><BR /><DIV CLASS=JDHint>
282     * <B STYLE="color: red;">Multiple-Match Scenarious:</B> If there are substring's within
283     * parameter {@code 'matchStrs'} such that the loop-iterations of this method could select
284     * multiple, different {@code String's} as a substring match with the input parameter
285     * {@code 's'}, then the loops will <I><B>always replace the first match found with input
286     * {@code String[] array} parameter {@code 'matchStrs'}</I></B>.
287     * </DIV>
288     * 
289     * @param replaceChars This is also a {@code char[] array}.  Every time a copy of any of the
290     * {@code 'matchStrs'} is found within {@code 's'}, the index of the {@code String} match from
291     * {@code 'matchStrs'} shall be used to lookup the parallel {@code 'replaceChar'}, and used
292     * to over-write or replace that character inside {@code 's'}.
293     * 
294     * <BR /><BR /><DIV CLASS=JDHint>
295     * <B STYLE="color: red;">Parallel Array:</B> This array should be considered parallel to input
296     * {@code String[] array 'matchStrs'}.  It provides a replacement mapping.  It is required to
297     * be the exact same length as array {@code 'matchStrs'}, or an exception shall throw.
298     * </DIV>
299     * 
300     * @return This shall return a new-{@code String} where the replacements that were requested
301     * have been substituted.
302     * 
303     * @throws NullPointerException If any of the {@code String's} inside the {@code String[]
304     * matchStrs} are null pointers.
305     * 
306     * @throws ParallelArrayException If the arrays {@code matchStrs} and {@code replaceChars}
307     * are not identical lengths.  These arrays must be parallel
308     */
309    @LinkJavaSource(handle="StrArrToCharArr")
310    public static String r(
311            boolean     ignoreCase,
312            String      s,
313            String[]    matchStrs,
314            char[]      replaceChars
315        )
316    { return StrArrToCharArr.replace(ignoreCase, s, matchStrs, replaceChars); }
317
318    /**
319     * Convenience Method.
320     * <BR />Case-Sensitive
321     * <BR />See Documentation: {@link #r(boolean, String, char[], String[])}
322     */
323    @LinkJavaSource(handle="CharArrToStrArr")
324    public static String r(String s, char[] matchChars, String[] replaceStrs)
325    { return CharArrToStrArr.replace(false, s, matchChars, replaceStrs); }
326
327    /**
328     * This shall replace each instance of the characters of parameter {@code 'matchStrs'} in input
329     * {@code String 's'} with the {@code String's} of <I><B>parallel array</I></B>
330     * {@code 'replaceStrs'}.
331     *
332     * @param ignoreCase When this parameter is set to {@code TRUE}, then the comparisons that
333     * determine whether a match has occurred shall ignore the case of the characters involved.
334     * 
335     * @param s This may be any Java {@code String}.
336     * 
337     * @param matchChars This is a {@code char[] array} that should hold some set of characters
338     * which are expected to be contained within the input parameter {@code 's'}.  This method
339     * shall search {@code 's'} - <I>left to right</I> - for any instances of the list of
340     * {@code 'matchChars'} and replace those characters with whatever {@code String} is in the
341     * <I>same array-index location (parallel-array)</I> from input parameter
342     * {@code 'replaceStrs'}
343     *  
344     * <BR /><BR /><DIV CLASS=JDHint>
345     * <B STYLE="color: red;">Multiple-Match Scenarious:</B> If there are multiple copies of an the
346     * <I>exact same character</I> in input parameter {@code 'matchChars'}, this should be
347     * considered an error-case.  The code in this method does not actually go into that level of
348     * error checking, and as such, if parameter {@code 'matchChars'} attempts to map the same
349     * {@code char} to more than one replacement-{@code String}, the loop will simply use the
350     * first-mapping found in {@code 'replaceStrs'} that is found.  No exceptions will throw when
351     * presented with this type of input.
352     * </DIV>
353     *
354     * <BR /><DIV CLASS=JDHint>
355     * <B STYLE="color: red;">Furthermore:</B> If an upper-case and lower-case version of the
356     * <I>exact same character</I> is provided in {@code char[] array} parameter
357     * {@code 'matchChars'}, and the {@code boolean flag} parameter {@code 'ignoreCase'} were set
358     * to {@code TRUE}, whichever of the two characters (upper-case or lower-case) that <I>occurs
359     * first in array parameter {@code 'matchChars'}</I> would be used to provide a
360     * replacement-{@code String} from array parameter {@code 'replaceStrs'}
361     * </DIV>
362     * 
363     * @param replaceStrs This is a {@code String[] array} that should hold sub-strings.
364     * Every time a copy of any of the {@code 'matchChars'} is found within {@code 's'}, the
365     * index of the character match from {@code 'matchChars'} shall be used to lookup the parallel
366     * {@code 'replaceStr'}, and used to over-write or replace that character inside {@code 's'}.
367     * 
368     * <BR /><BR /><DIV CLASS=JDHint>
369     * <B STYLE="color: red;">Parallel Array:</B> This array should be considered parallel to input
370     * {@code String[] array 'matchChars'}.  It provides a replacement mapping.  It is required to
371     * be the exact same length as array {@code 'matchChars'}, or an exception shall throw.
372     * </DIV>
373     * 
374     * @return This shall return a new-{@code String} where the replacements that were requested
375     * have been substituted.
376     * 
377     * @throws NullPointerException If any of the {@code String's} inside {@code String[]
378     * replaceStrs} are null.
379     * 
380     * @throws ParallelArrayException If the length of array {@code matchChars} does not equal
381     * the length of array {@code replaceStrs}, then this exception shall throw.   This is because
382     * these arrays are intended to be parallel arrays, where the references in the second array
383     * are supposed to be used to replace sub-strings (in {@code 's'}) from the first array.
384     */
385    @LinkJavaSource(handle="CharArrToStrArr")
386    public static String r(
387            boolean     ignoreCase,
388            String      s,
389            char[]      matchChars,
390            String[]    replaceStrs
391        )
392    { return CharArrToStrArr.replace(ignoreCase, s, matchChars, replaceStrs); }
393
394    /**
395     * Convenience Method.
396     * <BR />Case-Sensitive
397     * <BR />See Documentation: {@link #r(boolean, String, char[], IntCharFunction)}
398     */
399    @LinkJavaSource(handle="CharArrToStrReplFunc")
400    public static String r
401        (String s, char[] matchChars, IntCharFunction<String> replaceFunction)
402    { return CharArrToStrReplFunc.replace(false, s, matchChars, replaceFunction); }
403
404    /**
405     * This shall replace each instance of the characters of parameter {@code 'matchStrs'} in input
406     * {@code String 's'} with the {@code String}-value returned by the {@code 'replaceFunction'}
407     * lambda-method / {@code functional-interface}.
408     *
409     * <DIV CLASS="EXAMPLE">{@code
410     * // THIS EXAMPLE SHOWS HOW THIS METHOD CAN BE USED WITH REGULAR-EXPRESSION PROCESSING.
411     *
412     * // These are (some / most) of the characters that would need to be 'escaped' to use
413     * // them for the actual characters they represent inside of a Regular-Expression Pattern.
414     * final char[] CHARS_TO_ESCAPE = { '*', '.', '[', ']', '(', ')', '+', '|', '?', ':' };
415     *
416     * // This method invocation uses a lambda-expression that simply "prepends" a forward
417     * // slash to whatever character is being replaced with a String.  This will "escape" any
418     * // punctuation in the text that needs to "bypass" the Regular-Expression Engine - meaning
419     * // that these symbols, when found inside the text, should not be interpreted as commands
420     * // to RegEx, but rather as plain old brackets, parenthesis, periods, etc...
421     * text = StrReplace.r(text, CHARS_TO_ESCAPE, (int i, char c) -> "\\" + c);
422     * }</DIV>
423     * 
424     * @param ignoreCase When this parameter is set to {@code TRUE}, then the comparisons that
425     * determine whether a match has occurred shall ignore the case of the characters involved.
426     * 
427     * @param s This may be any Java {@code String}.
428     * 
429     * @param matchChars This is a {@code char[] array} that should hold some set of characters
430     * which are expected to be contained within the input parameter {@code 's'}.  This method
431     * shall search {@code 's'} - <I>left to right</I> - for any instances of the list of
432     * {@code 'matchChars'} and replace those characters with the results from input 
433     * {@code functional-interface} parameter {@code 'replaceFunction'}.
434     * 
435     * @param replaceFunction This shall receive any Java {@code 'char'} along with the index into
436     * {@code String 's'} where that {@code 'char'} is located.  This function must reply with a
437     * replace-{@code String}.  This shall be used to replace any instances of that character
438     * found inside the input {@code String}.
439     * 
440     * <EMBED CLASS='external-html' DATA-IN=char DATA-OUT=String
441     *      DATA-FILE-ID=STR_REPLACE_LOOK_AR>
442     * 
443     * @return This shall return a new-{@code String} where the replacements that were requested
444     * have been substituted.
445     */
446    @LinkJavaSource(handle="CharArrToStrReplFunc")
447    public static String r(
448            boolean                 ignoreCase,
449            String                  s,
450            char[]                  matchChars,
451            IntCharFunction<String> replaceFunction
452        )
453    { return CharArrToStrReplFunc.replace(ignoreCase, s, matchChars, replaceFunction); }
454
455    /**
456     * Convenience Method.
457     * <BR />Case-Sensitive
458     * <BR />See Documentation: {@link #r(boolean, String, char[], char[])}
459     */
460    @LinkJavaSource(handle="CharArrToCharArr")
461    public static String r(String s, char[] matchChars, char[] replaceChars)
462    { return CharArrToCharArr.replace(false, s, matchChars, replaceChars); }
463
464    /**
465     * This shall replace any instance of any of the characters in array-parameter 
466     * {@code 'matchChars'} with the character's provided in array-parameter
467     * {@code 'replaceChars'}.
468     * 
469     * <DIV CLASS="EXAMPLE">{@code
470     * // In this example, some of the Higher-Order UNICODE Punctuation Characters are replaced
471     * // With simple ASCII-Versions of similar punctuation symbols.  Occasionally, foreign
472     * // language news-sources will utilize these "Alternate Punctuation Symbols" in Asian
473     * // Language Texts.  Translating these documents necessitates converting these to simple
474     * // ASCII versions of the punctuation, for readability purposes.  (Since translated text
475     * // in English wouldn't need to use these symbols).
476     *
477     * char[] unicodeChars = { '〔', '〕', '〈', '〉', '《', '》', '「', '」', '〖', '〗', '【', '】' };
478     * char[] replacements = { '[',  ']',  '<', '>',  '\"', '\"', '[',  ']',  '{',  '}',  '<',  '>' };
479     * String theString    = "会议强调,制定出台《中国共产党中央委员会工作条例》";
480     * 
481     * // Use this method to replace all instance of the mentioned UNICODE characters with 
482     * // standard punctuation.  Note, after replacing the punctuation, translation would occur
483     * // in the next step...
484     * System.out.println(StrReplace.r(theString, unicodeChars, replacements));
485     * 
486     * // Prints:
487     * // 会议强调,制定出台"中国共产党中央委员会工作条例"
488     * // Which translates to:
489     * // The meeting emphasized the formulation and promulgation of the "Regulations on the Work
490     * // of the Central Committee of the Communist Party of China"
491     * }</DIV>
492     * 
493     * @param ignoreCase When this parameter is set to {@code TRUE}, then the comparisons that
494     * determine whether a match has occurred shall ignore the case of the characters involved.
495     * 
496     * @param s This may be any valid Java {@code String}.  It is expected to contain at least
497     * some of the characters that are listed in parameter {@code 'matchChars'}.
498     * 
499     * @param matchChars This is a {@code char[] array} that should hold some set of characters
500     * which are expected to be contained within the input parameter {@code 's'}.  This method
501     * shall search {@code 's'} - <I>left to right</I> - for any instances of the list of
502     * {@code 'matchChars'} and replace those characters with whatever {@code char} is in the
503     * <I>same array-index location (parallel-array)</I> from input parameter
504     * {@code 'replaceChars'}
505     * 
506     * <BR /><BR /><DIV CLASS=JDHint>
507     * <B STYLE="color: red;">Multiple-Match Scenarious:</B> If there are multiple copies of an the
508     * <I>exact same character</I> in input parameter {@code 'matchChars'}, this should be
509     * considered an error-case.  The code in this method does not actually go into that level of
510     * error checking, and as such, if parameter {@code 'matchChars'} attempts to map the same
511     * {@code char} to more than one replacement-{@code char}, the loop will simply use the first
512     *-mapping found in {@code 'replaceStrs'} that is found.  No exceptions will throw when
513     * presented with this type of input.
514     * </DIV>
515     *
516     * @param replaceChars This is also a {@code char[] array}.  Every time a copy of any of the
517     * {@code 'matchChars'} is found within {@code 's'}, the index of the character match from
518     * {@code 'matchChars'} shall be used to lookup the parallel {@code 'replaceChar'}, and used
519     * to over-write or replace that character inside {@code 's'}.
520     * 
521     * <BR /><BR /><DIV CLASS=JDHint>
522     * <B STYLE="color: red;">Parallel Array:</B> This array should be considered parallel to input
523     * {@code String[] array 'matchChars'}.  It provides a replacement mapping.  It is required to
524     * be the exact same length as array {@code 'matchChars'}, or an exception shall throw.
525     * </DIV>
526     * 
527     * @return This shall return a copy of the input {@code String}, with all characters that
528     * matched the characters in {@code 'matchChars'}, <I>replaced by the characters in 
529     * {@code 'replaceChars'}</I>.
530     * 
531     * @throws ParallelArrayException If the length of the {@code 'matchChars' array} is not
532     * equal to the length of the {@code 'replaceChars'} array.
533     */
534    @LinkJavaSource(handle="CharArrToCharArr")
535    public static String r(
536            boolean ignoreCase,
537            String  s,
538            char[]  matchChars,
539            char[]  replaceChars
540        )
541    { return CharArrToCharArr.replace(ignoreCase, s, matchChars, replaceChars); }
542
543    /**
544     * Convenience Method.
545     * <BR />Case-Sensitive
546     * <BR />See Documentation: {@link #r(boolean, String, char[], char)}
547     */
548    @LinkJavaSource(handle="CharArrPrepend")
549    public static String r(String s, char[] matchChars, char prependChar)
550    { return CharArrPrepend.replace(false, s, matchChars, prependChar); }
551
552    /**
553     * This shall "prepend" a specified / chosen character before each instance of a list
554     * of characters in an input-{@code String}.  {@code LAY-SPEAK:} If, for example, the
555     * {@code 'prependChar'} provided were the back-slash character {@code '\'}, then this
556     * method would insert a back-slash before each and every one of the {@code 'matchChars'}
557     * that it found inside {@code 's'}.
558     * 
559     * <BR /><BR />This method is used to escape certain characters for things like regular
560     * expressions and javascript.  Note the examples below.  These two methods are provided in
561     * {@link StrSource}.  These methods are {@link StrSource#escStrForRegEx(String)},
562     * {@link StrSource#escStrForJavaScript(String)}.
563     * 
564     * <DIV CLASS="EXAMPLE">{@code 
565     * private static final char[] JS_ESCAPE_CHARS_ARR = { '\\', '/', '\n', '\"' };
566     * 
567     * // When using Java to build Java-Script "Strings", escape these characters
568     * public static String escStrForJavaScript(String str)
569     * { return StrReplace.r(str, JS_ESCAPE_CHARS_ARR, '\\'); }
570     * 
571     * // This is a list of "control characters" for regular-expressions.  These characters
572     * // need to be escaped if they are expected to be taken literally, rather than as a control
573     * // character in regex.
574     * 
575     * private static final char[] REGEX_ESCAPE_CHARS_ARR =
576     * { '\\', '/', '(', ')', '[', ']', '{', '}', '$', '^', '+', '*', '?', '-', '.' };
577     * 
578     * public static String escStrForRegEx(String str)
579     * { return StrReplace.r(str, REGEX_ESCAPE_CHARS_ARR, '\\'); }
580     * }</DIV>
581     * 
582     * @param ignoreCase When this parameter is set to {@code TRUE}, then the comparisons that
583     * determine whether a match has occurred shall ignore the case of the characters involved.
584     *
585     * @param s This may be any valid Java {@code String}.  It is expected to contain at least
586     * some of the characters that are listed in parameter {@code 'matchChars'}.
587     * 
588     * @param matchChars This is a {@code char[] array} that should hold some set of characters
589     * which are expected to be contained within the input parameter {@code 's'}.  This method
590     * shall search {@code 's'} - <I>left to right</I> - for any instances of the list of
591     * {@code 'matchChars'} and insert the character {@code 'prependChar'} directly before each
592     * match-character identified in {@code String}-parameter {@code 's'}.
593     * 
594     * @param prependChar This character will be inserted directly before each instance of 
595     * {@code matcChars}-characters that are found within input {@code String}-parameter
596     * {@code 's'}
597     * 
598     * @return This shall return a new {@code String} with the {@code 'prependChar'} before each
599     * instance of one of the {@code 'matchChars'} identified in the original {@code String 's'}.
600     */
601    @LinkJavaSource(handle="CharArrPrepend")
602    public static String r(
603            boolean ignoreCase,
604            String  s,
605            char[]  matchChars,
606            char    prependChar
607        )
608    { return CharArrPrepend.replace(ignoreCase, s, matchChars, prependChar); }
609
610    /**
611     * Convenience Method.
612     * <BR />See Documentation: {@link #r(String, boolean, char[], ToCharIntCharFunc)}
613     */
614    @LinkJavaSource(handle="CharArrToCharReplFunc")
615    public static String r(char[] matchChars, ToCharIntCharFunc replaceFunction, String s)
616    { return CharArrToCharReplFunc.replace(s, false, matchChars, replaceFunction); }
617
618    /**
619     * This method shall receive a list of {@code 'char'}, and then search the input
620     * {@code String} parameter {@code 's'} for any instances of the characters listed in
621     * {@code 'matchChars'} - and replace them.  The replacement characters must be provided
622     * by the Functional-Interface Parameter {@code 'replaceFunction'}.
623     * 
624     * <BR /><BR />The character-equality comparisons may be done in a case-insensitive manner,
625     * if requested (using the {@code 'ignoreCase'} parameter).
626     * 
627     * @param s This may be any valid Java {@code String}.  It is expected to contain at least
628     * some of the characters that are listed in parameter {@code 'matchChars'}.
629     * 
630     * @param ignoreCase If this parameter receives {@code TRUE}, then the equality comparisons
631     * between the input {@code String 's'}, and {@code 'matchChars'} will be done on a case
632     * insensitive basis.
633     * 
634     * @param matchChars This is a {@code char[] array} that should hold some set of characters
635     * which are expected to be contained insiide the input parameter {@code 's'}.  This method
636     * shall search {@code 's'} - <I>left to right</I> - for any instances of the list of
637     * {@code 'matchChars'} and replace those characters with ones returned by
638     * {@code 'replaceFunction.apply(i, c);'}.  Note that, here, {@code 'i'} is the
639     * {@code String}-index where the {@code 'matchChar'} was found, and {@code 'c'} is the 
640     * character that was matched.
641     * 
642     * @param replaceFunction This shall receive any Java {@code 'char'} along with the index into
643     * {@code String 's'} where that {@code 'char'} is located.  This function must reply with a
644     * replace-{@code char}.  This shall be used to replace instances of that character
645     * found inside the input {@code String}. 
646     * 
647     * <EMBED CLASS='external-html' DATA-IN=char DATA-OUT=char
648     *      DATA-FILE-ID=STR_REPLACE_LOOK_AR>
649     * 
650     * @return A new {@code String} where any and all characters that were listed in 
651     * {@code 'matchChars'} have been replaced by the return-values of {@code 'replaceFunction'}.
652     */
653    @LinkJavaSource(handle="CharArrToCharReplFunc")
654    public static String r(
655            String              s,
656            boolean             ignoreCase,
657            char[]              matchChars,
658            ToCharIntCharFunc   replaceFunction
659        )
660    { return CharArrToCharReplFunc.replace(s, ignoreCase, matchChars, replaceFunction); }
661}