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