001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017
018package org.apache.commons.text.lookup;
019
020import java.util.Map;
021
022import org.apache.commons.text.StringSubstitutor;
023
024/**
025 * Provides access to lookups defined in this package.
026 * <p>
027 * The default lookups are:
028 * </p>
029 * <table>
030 * <caption>Default String Lookups</caption>
031 * <tr>
032 * <th>Key</th>
033 * <th>Implementation</th>
034 * <th>Factory Method</th>
035 * <th>Since</th>
036 * </tr>
037 * <tr>
038 * <td>{@value #KEY_BASE64_DECODER}</td>
039 * <td>{@link Base64DecoderStringLookup}</td>
040 * <td>{@link #base64DecoderStringLookup()}</td>
041 * <td>1.6</td>
042 * </tr>
043 * <tr>
044 * <td>{@value #KEY_BASE64_ENCODER}</td>
045 * <td>{@link Base64EncoderStringLookup}</td>
046 * <td>{@link #base64EncoderStringLookup()}</td>
047 * <td>1.6</td>
048 * </tr>
049 * <tr>
050 * <td>{@value #KEY_CONST}</td>
051 * <td>{@link ConstantStringLookup}</td>
052 * <td>{@link #constantStringLookup()}</td>
053 * <td>1.5</td>
054 * </tr>
055 * <tr>
056 * <td>{@value #KEY_DATE}</td>
057 * <td>{@link DateStringLookup}</td>
058 * <td>{@link #dateStringLookup()}</td>
059 * <td>1.5</td>
060 * </tr>
061 * <tr>
062 * <td>{@value #KEY_DNS}</td>
063 * <td>{@link DnsStringLookup}</td>
064 * <td>{@link #dnsStringLookup()}</td>
065 * <td>1.8</td>
066 * </tr>
067 * <tr>
068 * <td>{@value #KEY_ENV}</td>
069 * <td>{@link EnvironmentVariableStringLookup}</td>
070 * <td>{@link #environmentVariableStringLookup()}</td>
071 * <td>1.3</td>
072 * </tr>
073 * <tr>
074 * <td>{@value #KEY_FILE}</td>
075 * <td>{@link FileStringLookup}</td>
076 * <td>{@link #fileStringLookup()}</td>
077 * <td>1.5</td>
078 * </tr>
079 * <tr>
080 * <td>{@value #KEY_JAVA}</td>
081 * <td>{@link JavaPlatformStringLookup}</td>
082 * <td>{@link #javaPlatformStringLookup()}</td>
083 * <td>1.5</td>
084 * </tr>
085 * <tr>
086 * <td>{@value #KEY_LOCALHOST}</td>
087 * <td>{@link LocalHostStringLookup}</td>
088 * <td>{@link #localHostStringLookup()}</td>
089 * <td>1.3</td>
090 * </tr>
091 * <tr>
092 * <td>{@value #KEY_PROPERTIES}</td>
093 * <td>{@link PropertiesStringLookup}</td>
094 * <td>{@link #propertiesStringLookup()}</td>
095 * <td>1.5</td>
096 * </tr>
097 * <tr>
098 * <td>{@value #KEY_RESOURCE_BUNDLE}</td>
099 * <td>{@link ResourceBundleStringLookup}</td>
100 * <td>{@link #resourceBundleStringLookup()}</td>
101 * <td>1.6</td>
102 * </tr>
103 * <tr>
104 * <td>{@value #KEY_SCRIPT}</td>
105 * <td>{@link ScriptStringLookup}</td>
106 * <td>{@link #scriptStringLookup()}</td>
107 * <td>1.5</td>
108 * </tr>
109 * <tr>
110 * <td>{@value #KEY_SYS}</td>
111 * <td>{@link SystemPropertyStringLookup}</td>
112 * <td>{@link #systemPropertyStringLookup()}</td>
113 * <td>1.3</td>
114 * </tr>
115 * <tr>
116 * <td>{@value #KEY_URL}</td>
117 * <td>{@link UrlStringLookup}</td>
118 * <td>{@link #urlStringLookup()}</td>
119 * <td>1.5</td>
120 * </tr>
121 * <tr>
122 * <td>{@value #KEY_URL_DECODER}</td>
123 * <td>{@link UrlDecoderStringLookup}</td>
124 * <td>{@link #urlDecoderStringLookup()}</td>
125 * <td>1.5</td>
126 * </tr>
127 * <tr>
128 * <td>{@value #KEY_URL_ENCODER}</td>
129 * <td>{@link UrlEncoderStringLookup}</td>
130 * <td>{@link #urlEncoderStringLookup()}</td>
131 * <td>1.5</td>
132 * </tr>
133 * <tr>
134 * <td>{@value #KEY_XML}</td>
135 * <td>{@link XmlStringLookup}</td>
136 * <td>{@link #xmlStringLookup()}</td>
137 * <td>1.5</td>
138 * </tr>
139 * </table>
140 *
141 * @since 1.3
142 */
143public final class StringLookupFactory {
144
145    /**
146     * Defines the singleton for this class.
147     */
148    public static final StringLookupFactory INSTANCE = new StringLookupFactory();
149
150    /**
151     * Default lookup key for interpolation {@value #KEY_BASE64_DECODER}.
152     *
153     * @since 1.6
154     */
155    public static final String KEY_BASE64_DECODER = "base64Decoder";
156
157    /**
158     * Default lookup key for interpolation {@value #KEY_BASE64_ENCODER}.
159     *
160     * @since 1.6
161     */
162    public static final String KEY_BASE64_ENCODER = "base64Encoder";
163
164    /**
165     * Default lookup key for interpolation {@value #KEY_CONST}.
166     *
167     * @since 1.6
168     */
169    public static final String KEY_CONST = "const";
170
171    /**
172     * Default lookup key for interpolation {@value #KEY_DATE}.
173     *
174     * @since 1.6
175     */
176    public static final String KEY_DATE = "date";
177
178    /**
179     * Default lookup key for interpolation {@value #KEY_DNS}.
180     *
181     * @since 1.8
182     */
183    public static final String KEY_DNS = "dns";
184
185    /**
186     * Default lookup key for interpolation {@value #KEY_ENV}.
187     *
188     * @since 1.6
189     */
190    public static final String KEY_ENV = "env";
191
192    /**
193     * Default lookup key for interpolation {@value #KEY_FILE}.
194     *
195     * @since 1.6
196     */
197    public static final String KEY_FILE = "file";
198
199    /**
200     * Default lookup key for interpolation {@value #KEY_JAVA}.
201     *
202     * @since 1.6
203     */
204    public static final String KEY_JAVA = "java";
205
206    /**
207     * Default lookup key for interpolation {@value #KEY_LOCALHOST}.
208     *
209     * @since 1.6
210     */
211    public static final String KEY_LOCALHOST = "localhost";
212
213    /**
214     * Default lookup key for interpolation {@value #KEY_PROPERTIES}.
215     *
216     * @since 1.6
217     */
218    public static final String KEY_PROPERTIES = "properties";
219
220    /**
221     * Default lookup key for interpolation {@value #KEY_RESOURCE_BUNDLE}.
222     *
223     * @since 1.6
224     */
225    public static final String KEY_RESOURCE_BUNDLE = "resourceBundle";
226
227    /**
228     * Default lookup key for interpolation {@value #KEY_SCRIPT}.
229     *
230     * @since 1.6
231     */
232    public static final String KEY_SCRIPT = "script";
233
234    /**
235     * Default lookup key for interpolation {@value #KEY_SYS}.
236     *
237     * @since 1.6
238     */
239    public static final String KEY_SYS = "sys";
240
241    /**
242     * Default lookup key for interpolation {@value #KEY_URL}.
243     *
244     * @since 1.6
245     */
246    public static final String KEY_URL = "url";
247
248    /**
249     * Default lookup key for interpolation {@value #KEY_URL_DECODER}.
250     *
251     * @since 1.6
252     */
253    public static final String KEY_URL_DECODER = "urlDecoder";
254
255    /**
256     * Default lookup key for interpolation {@value #KEY_URL_ENCODER}.
257     *
258     * @since 1.6
259     */
260    public static final String KEY_URL_ENCODER = "urlEncoder";
261
262    /**
263     * Default lookup key for interpolation {@value #KEY_XML}.
264     *
265     * @since 1.6
266     */
267    public static final String KEY_XML = "xml";
268
269    /**
270     * Clears any static resources.
271     *
272     * @since 1.5
273     */
274    public static void clear() {
275        ConstantStringLookup.clear();
276    }
277
278    /**
279     * No need to build instances for now.
280     */
281    private StringLookupFactory() {
282        // empty
283    }
284
285    /**
286     * Adds the {@link StringLookupFactory default lookups}.
287     *
288     * @param stringLookupMap the map of string lookups.
289     * @since 1.5
290     */
291    public void addDefaultStringLookups(final Map<String, StringLookup> stringLookupMap) {
292        if (stringLookupMap != null) {
293            // "base64" is deprecated in favor of KEY_BASE64_DECODER.
294            stringLookupMap.put("base64", Base64DecoderStringLookup.INSTANCE);
295            for (final DefaultStringLookup stringLookup : DefaultStringLookup.values()) {
296                stringLookupMap.put(InterpolatorStringLookup.toKey(stringLookup.getKey()),
297                        stringLookup.getStringLookup());
298            }
299        }
300    }
301
302    /**
303     * Returns the Base64DecoderStringLookup singleton instance to decode Base64 strings.
304     * <p>
305     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
306     * </p>
307     *
308     * <pre>
309     * StringLookupFactory.INSTANCE.base64DecoderStringLookup().lookup("SGVsbG9Xb3JsZCE=");
310     * </pre>
311     * <p>
312     * Using a {@link StringSubstitutor}:
313     * </p>
314     *
315     * <pre>
316     * StringSubstitutor.createInterpolator().replace("... ${base64Decoder:SGVsbG9Xb3JsZCE=} ..."));
317     * </pre>
318     * <p>
319     * The above examples convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}.
320     * </p>
321     *
322     * @return The DateStringLookup singleton instance.
323     * @since 1.5
324     */
325    public StringLookup base64DecoderStringLookup() {
326        return Base64DecoderStringLookup.INSTANCE;
327    }
328
329    /**
330     * Returns the Base64EncoderStringLookup singleton instance to encode strings to Base64.
331     * <p>
332     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
333     * </p>
334     *
335     * <pre>
336     * StringLookupFactory.INSTANCE.base64EncoderStringLookup().lookup("HelloWorld!");
337     * </pre>
338     * <p>
339     * Using a {@link StringSubstitutor}:
340     * </p>
341     *
342     * <pre>
343     * StringSubstitutor.createInterpolator().replace("... ${base64Encoder:HelloWorld!} ..."));
344     * </pre>
345     * <p>
346     * The above examples convert {@code } to {@code "SGVsbG9Xb3JsZCE="}.
347     * </p>
348     *
349     * @return The DateStringLookup singleton instance.
350     * @since 1.6
351     */
352    public StringLookup base64EncoderStringLookup() {
353        return Base64EncoderStringLookup.INSTANCE;
354    }
355
356    /**
357     * Returns the Base64DecoderStringLookup singleton instance to decode Base64 strings.
358     * <p>
359     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
360     * </p>
361     *
362     * <pre>
363     * StringLookupFactory.INSTANCE.base64DecoderStringLookup().lookup("SGVsbG9Xb3JsZCE=");
364     * </pre>
365     * <p>
366     * Using a {@link StringSubstitutor}:
367     * </p>
368     *
369     * <pre>
370     * StringSubstitutor.createInterpolator().replace("... ${base64Decoder:SGVsbG9Xb3JsZCE=} ..."));
371     * </pre>
372     * <p>
373     * The above examples convert {@code "SGVsbG9Xb3JsZCE="} to {@code "HelloWorld!"}.
374     * </p>
375     *
376     * @return The DateStringLookup singleton instance.
377     * @since 1.5
378     * @deprecated Use {@link #base64DecoderStringLookup()}.
379     */
380    @Deprecated
381    public StringLookup base64StringLookup() {
382        return Base64DecoderStringLookup.INSTANCE;
383    }
384
385    /**
386     * Returns the ConstantStringLookup singleton instance to look up the value of a fully-qualified static final value.
387     * <p>
388     * Sometimes it is necessary in a configuration file to refer to a constant defined in a class. This can be done
389     * with this lookup implementation. Variable names must be in the format {@code apackage.AClass.AFIELD}. The
390     * {@code lookup(String)} method will split the passed in string at the last dot, separating the fully qualified
391     * class name and the name of the constant (i.e. <b>static final</b>) member field. Then the class is loaded and the
392     * field's value is obtained using reflection.
393     * </p>
394     * <p>
395     * Once retrieved values are cached for fast access. This class is thread-safe. It can be used as a standard (i.e.
396     * global) lookup object and serve multiple clients concurrently.
397     * </p>
398     * <p>
399     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
400     * </p>
401     *
402     * <pre>
403     * StringLookupFactory.INSTANCE.constantStringLookup().lookup("java.awt.event.KeyEvent.VK_ESCAPE");
404     * </pre>
405     * <p>
406     * Using a {@link StringSubstitutor}:
407     * </p>
408     *
409     * <pre>
410     * StringSubstitutor.createInterpolator().replace("... ${const:java.awt.event.KeyEvent.VK_ESCAPE} ..."));
411     * </pre>
412     * <p>
413     * The above examples convert {@code java.awt.event.KeyEvent.VK_ESCAPE} to {@code "27"}.
414     * </p>
415     *
416     * @return The DateStringLookup singleton instance.
417     * @since 1.5
418     */
419    public StringLookup constantStringLookup() {
420        return ConstantStringLookup.INSTANCE;
421    }
422
423    /**
424     * Returns the DateStringLookup singleton instance to format the current date with the format given in the key in a
425     * format compatible with {@link java.text.SimpleDateFormat}.
426     * <p>
427     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
428     * </p>
429     *
430     * <pre>
431     * StringLookupFactory.INSTANCE.dateStringLookup().lookup("yyyy-MM-dd");
432     * </pre>
433     * <p>
434     * Using a {@link StringSubstitutor}:
435     * </p>
436     *
437     * <pre>
438     * StringSubstitutor.createInterpolator().replace("... ${date:yyyy-MM-dd} ..."));
439     * </pre>
440     * <p>
441     * The above examples convert {@code "yyyy-MM-dd"} to todays's date, for example, {@code "2019-08-04"}.
442     * </p>
443     *
444     * @return The DateStringLookup singleton instance.
445     */
446    public StringLookup dateStringLookup() {
447        return DateStringLookup.INSTANCE;
448    }
449
450    /**
451     * Returns the EnvironmentVariableStringLookup singleton instance where the lookup key is an environment variable
452     * name.
453     * <p>
454     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
455     * </p>
456     *
457     * <pre>
458     * StringLookupFactory.INSTANCE.dateStringLookup().lookup("USER");
459     * </pre>
460     * <p>
461     * Using a {@link StringSubstitutor}:
462     * </p>
463     *
464     * <pre>
465     * StringSubstitutor.createInterpolator().replace("... ${env:USER} ..."));
466     * </pre>
467     * <p>
468     * The above examples convert (on Linux) {@code "USER"} to the current user name. On Windows 10, you would use
469     * {@code "USERNAME"} to the same effect.
470     * </p>
471     *
472     * @return The EnvironmentVariableStringLookup singleton instance.
473     */
474    public StringLookup environmentVariableStringLookup() {
475        return EnvironmentVariableStringLookup.INSTANCE;
476    }
477
478    /**
479     * Returns the FileStringLookup singleton instance.
480     * <p>
481     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
482     * </p>
483     *
484     * <pre>
485     * StringLookupFactory.INSTANCE.fileStringLookup().lookup("UTF-8:com/domain/document.properties");
486     * </pre>
487     * <p>
488     * Using a {@link StringSubstitutor}:
489     * </p>
490     *
491     * <pre>
492     * StringSubstitutor.createInterpolator().replace("... ${file:UTF-8:com/domain/document.properties} ..."));
493     * </pre>
494     * <p>
495     * The above examples convert {@code "UTF-8:com/domain/document.properties"} to the contents of the file.
496     * </p>
497     *
498     * @return The FileStringLookup singleton instance.
499     * @since 1.5
500     */
501    public StringLookup fileStringLookup() {
502        return FileStringLookup.INSTANCE;
503    }
504
505    /**
506     * Returns a new InterpolatorStringLookup using the {@link StringLookupFactory default lookups}.
507     * <p>
508     * The lookups available to an interpolator are defined in
509     * </p>
510     * <p>
511     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
512     * </p>
513     *
514     * <pre>
515     * StringLookupFactory.INSTANCE.interpolatorStringLookup().lookup("${sys:os.name}, ${env:USER}");
516     * </pre>
517     * <p>
518     * Using a {@link StringSubstitutor}:
519     * </p>
520     *
521     * <pre>
522     * StringSubstitutor.createInterpolator().replace("... ${sys:os.name}, ${env:USER} ..."));
523     * </pre>
524     * <p>
525     * The above examples convert {@code "${sys:os.name}, ${env:USER}"} to the OS name and Linux user name.
526     * </p>
527     *
528     * @return a new InterpolatorStringLookup.
529     */
530    public StringLookup interpolatorStringLookup() {
531        return InterpolatorStringLookup.INSTANCE;
532    }
533
534    /**
535     * Returns a new InterpolatorStringLookup using the {@link StringLookupFactory default lookups}.
536     * <p>
537     * If {@code addDefaultLookups} is true, the following lookups are used in addition to the ones provided in
538     * {@code stringLookupMap}:
539     * </p>
540     *
541     * @param stringLookupMap     the map of string lookups.
542     * @param defaultStringLookup the default string lookup.
543     * @param addDefaultLookups   whether to use lookups as described above.
544     * @return a new InterpolatorStringLookup.
545     * @since 1.4
546     */
547    public StringLookup interpolatorStringLookup(final Map<String, StringLookup> stringLookupMap,
548            final StringLookup defaultStringLookup, final boolean addDefaultLookups) {
549        return new InterpolatorStringLookup(stringLookupMap, defaultStringLookup, addDefaultLookups);
550    }
551
552    /**
553     * Returns a new InterpolatorStringLookup using the {@link StringLookupFactory default lookups}.
554     *
555     * @param <V> the value type the default string lookup's map.
556     * @param map the default map for string lookups.
557     * @return a new InterpolatorStringLookup.
558     */
559    public <V> StringLookup interpolatorStringLookup(final Map<String, V> map) {
560        return new InterpolatorStringLookup(map);
561    }
562
563    /**
564     * Returns a new InterpolatorStringLookup using the {@link StringLookupFactory default lookups}.
565     *
566     * @param defaultStringLookup the default string lookup.
567     * @return a new InterpolatorStringLookup.
568     */
569    public StringLookup interpolatorStringLookup(final StringLookup defaultStringLookup) {
570        return new InterpolatorStringLookup(defaultStringLookup);
571    }
572
573    /**
574     * Returns the JavaPlatformStringLookup singleton instance. Looks up keys related to Java: Java version, JRE
575     * version, VM version, and so on.
576     * <p>
577     * The lookup keys with examples are:
578     * </p>
579     * <ul>
580     * <li><b>version</b>: "Java version 1.8.0_181"</li>
581     * <li><b>runtime</b>: "Java(TM) SE Runtime Environment (build 1.8.0_181-b13) from Oracle Corporation"</li>
582     * <li><b>vm</b>: "Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)"</li>
583     * <li><b>os</b>: "Windows 10 10.0, architecture: amd64-64"</li>
584     * <li><b>hardware</b>: "processors: 4, architecture: amd64-64, instruction sets: amd64"</li>
585     * <li><b>locale</b>: "default locale: en_US, platform encoding: iso-8859-1"</li>
586     * </ul>
587     *
588     * <p>
589     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
590     * </p>
591     *
592     * <pre>
593     * StringLookupFactory.INSTANCE.javaPlatformStringLookup().lookup("version");
594     * </pre>
595     * <p>
596     * Using a {@link StringSubstitutor}:
597     * </p>
598     *
599     * <pre>
600     * StringSubstitutor.createInterpolator().replace("... ${java:version} ..."));
601     * </pre>
602     * <p>
603     * The above examples convert {@code "version"} to the current VM version, for example,
604     * {@code "Java version 1.8.0_181"}.
605     * </p>
606     *
607     * @return The JavaPlatformStringLookup singleton instance.
608     */
609    public StringLookup javaPlatformStringLookup() {
610        return JavaPlatformStringLookup.INSTANCE;
611    }
612
613    /**
614     * Returns the LocalHostStringLookup singleton instance where the lookup key is one of:
615     * <ul>
616     * <li><b>name</b>: for the local host name, for example {@code EXAMPLE}.</li>
617     * <li><b>canonical-name</b>: for the local canonical host name, for example {@code EXAMPLE.apache.org}.</li>
618     * <li><b>address</b>: for the local host address, for example {@code 192.168.56.1}.</li>
619     * </ul>
620     *
621     * <p>
622     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
623     * </p>
624     *
625     * <pre>
626     * StringLookupFactory.INSTANCE.localHostStringLookup().lookup("canonical-name");
627     * </pre>
628     * <p>
629     * Using a {@link StringSubstitutor}:
630     * </p>
631     *
632     * <pre>
633     * StringSubstitutor.createInterpolator().replace("... ${localhost:canonical-name} ..."));
634     * </pre>
635     * <p>
636     * The above examples convert {@code "canonical-name"} to the current host name, for example,
637     * {@code "EXAMPLE.apache.org"}.
638     * </p>
639     *
640     * @return The DateStringLookup singleton instance.
641     */
642    public StringLookup localHostStringLookup() {
643        return LocalHostStringLookup.INSTANCE;
644    }
645
646    /**
647     * Returns the DnsStringLookup singleton instance where the lookup key is one of:
648     * <ul>
649     * <li><b>name</b>: for the local host name, for example {@code EXAMPLE} but also {@code EXAMPLE.apache.org}.</li>
650     * <li><b>canonical-name</b>: for the local canonical host name, for example {@code EXAMPLE.apache.org}.</li>
651     * <li><b>address</b>: for the local host address, for example {@code 192.168.56.1}.</li>
652     * </ul>
653     *
654     * <p>
655     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
656     * </p>
657     *
658     * <pre>
659     * StringLookupFactory.INSTANCE.dnsStringLookup().lookup("address|apache.org");
660     * </pre>
661     * <p>
662     * Using a {@link StringSubstitutor}:
663     * </p>
664     *
665     * <pre>
666     * StringSubstitutor.createInterpolator().replace("... ${dns:address|apache.org} ..."));
667     * </pre>
668     * <p>
669     * The above examples convert {@code "address|apache.org"} to {@code "95.216.24.32} (or {@code "40.79.78.1"}).
670     * </p>
671     *
672     * @return the DateStringLookup singleton instance.
673     * @since 1.8
674     */
675    public StringLookup dnsStringLookup() {
676        return DnsStringLookup.INSTANCE;
677    }
678
679    /**
680     * Returns a new map-based lookup where the request for a lookup is answered with the value for that key.
681     *
682     * @param <V> the map value type.
683     * @param map the map.
684     * @return a new MapStringLookup.
685     */
686    public <V> StringLookup mapStringLookup(final Map<String, V> map) {
687        return MapStringLookup.on(map);
688    }
689
690    /**
691     * Returns the NullStringLookup singleton instance which always returns null.
692     *
693     * @return The NullStringLookup singleton instance.
694     */
695    public StringLookup nullStringLookup() {
696        return NullStringLookup.INSTANCE;
697    }
698
699    /**
700     * Returns the PropertiesStringLookup singleton instance.
701     * <p>
702     * Looks up the value for the key in the format "DocumentPath::MyKey".
703     * </p>
704     * <p>
705     * Note the use of "::" instead of ":" to allow for "C:" drive letters in paths.
706     * </p>
707     * <p>
708     * For example: "com/domain/document.properties::MyKey".
709     * </p>
710     *
711     * <p>
712     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
713     * </p>
714     *
715     * <pre>
716     * StringLookupFactory.INSTANCE.propertiesStringLookup().lookup("com/domain/document.properties::MyKey");
717     * </pre>
718     * <p>
719     * Using a {@link StringSubstitutor}:
720     * </p>
721     *
722     * <pre>
723     * StringSubstitutor.createInterpolator().replace("... ${properties:com/domain/document.properties::MyKey} ..."));
724     * </pre>
725     * <p>
726     * The above examples convert {@code "com/domain/document.properties::MyKey"} to the key value in the properties
727     * file at the path "com/domain/document.properties".
728     * </p>
729     *
730     * @return The PropertiesStringLookup singleton instance.
731     * @since 1.5
732     */
733    public StringLookup propertiesStringLookup() {
734        return PropertiesStringLookup.INSTANCE;
735    }
736
737    /**
738     * Returns the ResourceBundleStringLookup singleton instance.
739     * <p>
740     * Looks up the value for a given key in the format "BundleName:BundleKey".
741     * </p>
742     * <p>
743     * For example: "com.domain.messages:MyKey".
744     * </p>
745     * <p>
746     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
747     * </p>
748     *
749     * <pre>
750     * StringLookupFactory.INSTANCE.resourceBundleStringLookup().lookup("com.domain.messages:MyKey");
751     * </pre>
752     * <p>
753     * Using a {@link StringSubstitutor}:
754     * </p>
755     *
756     * <pre>
757     * StringSubstitutor.createInterpolator().replace("... ${resourceBundle:com.domain.messages:MyKey} ..."));
758     * </pre>
759     * <p>
760     * The above examples convert {@code "com.domain.messages:MyKey"} to the key value in the resource bundle at
761     * {@code "com.domain.messages"}.
762     * </p>
763     *
764     * @return The ResourceBundleStringLookup singleton instance.
765     */
766    public StringLookup resourceBundleStringLookup() {
767        return ResourceBundleStringLookup.INSTANCE;
768    }
769
770    /**
771     * Returns a ResourceBundleStringLookup instance for the given bundle name.
772     * <p>
773     * Looks up the value for a given key in the format "MyKey".
774     * </p>
775     * <p>
776     * For example: "MyKey".
777     * </p>
778     * <p>
779     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
780     * </p>
781     *
782     * <pre>
783     * StringLookupFactory.INSTANCE.resourceBundleStringLookup("com.domain.messages").lookup("MyKey");
784     * </pre>
785     * <p>
786     * The above example converts {@code "MyKey"} to the key value in the resource bundle at
787     * {@code "com.domain.messages"}.
788     * </p>
789     *
790     * @param bundleName Only lookup in this bundle.
791     * @return a ResourceBundleStringLookup instance for the given bundle name.
792     * @since 1.5
793     */
794    public StringLookup resourceBundleStringLookup(final String bundleName) {
795        return new ResourceBundleStringLookup(bundleName);
796    }
797
798    /**
799     * Returns the ScriptStringLookup singleton instance.
800     * <p>
801     * Looks up the value for the key in the format "ScriptEngineName:Script".
802     * </p>
803     * <p>
804     * For example: "javascript:3 + 4".
805     * </p>
806     * <p>
807     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
808     * </p>
809     *
810     * <pre>
811     * StringLookupFactory.INSTANCE.scriptStringLookup().lookup("javascript:3 + 4");
812     * </pre>
813     * <p>
814     * Using a {@link StringSubstitutor}:
815     * </p>
816     *
817     * <pre>
818     * StringSubstitutor.createInterpolator().replace("... ${javascript:3 + 4} ..."));
819     * </pre>
820     * <p>
821     * The above examples convert {@code "javascript:3 + 4"} to {@code "7"}.
822     * </p>
823     *
824     * @return The ScriptStringLookup singleton instance.
825     * @since 1.5
826     */
827    public StringLookup scriptStringLookup() {
828        return ScriptStringLookup.INSTANCE;
829    }
830
831    /**
832     * Returns the SystemPropertyStringLookup singleton instance where the lookup key is a system property name.
833     *
834     * <p>
835     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
836     * </p>
837     *
838     * <pre>
839     * StringLookupFactory.INSTANCE.systemPropertyStringLookup().lookup("os.name");
840     * </pre>
841     * <p>
842     * Using a {@link StringSubstitutor}:
843     * </p>
844     *
845     * <pre>
846     * StringSubstitutor.createInterpolator().replace("... ${sys:os.name} ..."));
847     * </pre>
848     * <p>
849     * The above examples convert {@code "os.name"} to the operating system name.
850     * </p>
851     *
852     * @return The SystemPropertyStringLookup singleton instance.
853     */
854    public StringLookup systemPropertyStringLookup() {
855        return SystemPropertyStringLookup.INSTANCE;
856    }
857
858    /**
859     * Returns the UrlDecoderStringLookup singleton instance.
860     * <p>
861     * Decodes URL Strings using the UTF-8 encoding.
862     * </p>
863     * <p>
864     * For example: "Hello%20World%21" becomes "Hello World!".
865     * </p>
866     * <p>
867     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
868     * </p>
869     *
870     * <pre>
871     * StringLookupFactory.INSTANCE.urlDecoderStringLookup().lookup("Hello%20World%21");
872     * </pre>
873     * <p>
874     * Using a {@link StringSubstitutor}:
875     * </p>
876     *
877     * <pre>
878     * StringSubstitutor.createInterpolator().replace("... ${urlDecoder:Hello%20World%21} ..."));
879     * </pre>
880     * <p>
881     * The above examples convert {@code "Hello%20World%21"} to {@code "Hello World!"}.
882     * </p>
883     *
884     * @return The UrlStringLookup singleton instance.
885     * @since 1.6
886     */
887    public StringLookup urlDecoderStringLookup() {
888        return UrlDecoderStringLookup.INSTANCE;
889    }
890
891    /**
892     * Returns the UrlDecoderStringLookup singleton instance.
893     * <p>
894     * Decodes URL Strings using the UTF-8 encoding.
895     * </p>
896     * <p>
897     * For example: "Hello World!" becomes "Hello+World%21".
898     * </p>
899     * <p>
900     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
901     * </p>
902     *
903     * <pre>
904     * StringLookupFactory.INSTANCE.urlEncoderStringLookup().lookup("Hello World!");
905     * </pre>
906     * <p>
907     * Using a {@link StringSubstitutor}:
908     * </p>
909     *
910     * <pre>
911     * StringSubstitutor.createInterpolator().replace("... ${urlEncoder:Hello World!} ..."));
912     * </pre>
913     * <p>
914     * The above examples convert {@code "Hello World!"} to {@code "Hello%20World%21"}.
915     * </p>
916     *
917     * @return The UrlStringLookup singleton instance.
918     * @since 1.6
919     */
920    public StringLookup urlEncoderStringLookup() {
921        return UrlEncoderStringLookup.INSTANCE;
922    }
923
924    /**
925     * Returns the UrlStringLookup singleton instance.
926     * <p>
927     * Looks up the value for the key in the format "CharsetName:URL".
928     * </p>
929     * <p>
930     * For example, using the HTTP scheme: "UTF-8:http://www.google.com"
931     * </p>
932     * <p>
933     * For example, using the file scheme:
934     * "UTF-8:file:///C:/somehome/commons/commons-text/src/test/resources/document.properties"
935     * </p>
936     * <p>
937     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
938     * </p>
939     *
940     * <pre>
941     * StringLookupFactory.INSTANCE.urlStringLookup().lookup("UTF-8:https://www.apache.org");
942     * </pre>
943     * <p>
944     * Using a {@link StringSubstitutor}:
945     * </p>
946     *
947     * <pre>
948     * StringSubstitutor.createInterpolator().replace("... ${url:UTF-8:https://www.apache.org} ..."));
949     * </pre>
950     * <p>
951     * The above examples convert {@code "UTF-8:https://www.apache.org"} to the contents of that page.
952     * </p>
953     *
954     * @return The UrlStringLookup singleton instance.
955     * @since 1.5
956     */
957    public StringLookup urlStringLookup() {
958        return UrlStringLookup.INSTANCE;
959    }
960
961    /**
962     * Returns the XmlStringLookup singleton instance.
963     * <p>
964     * Looks up the value for the key in the format "DocumentPath:XPath".
965     * </p>
966     * <p>
967     * For example: "com/domain/document.xml:/path/to/node".
968     * </p>
969     * <p>
970     * Using a {@link StringLookup} from the {@link StringLookupFactory}:
971     * </p>
972     *
973     * <pre>
974     * StringLookupFactory.INSTANCE.xmlStringLookup().lookup("com/domain/document.xml:/path/to/node");
975     * </pre>
976     * <p>
977     * Using a {@link StringSubstitutor}:
978     * </p>
979     *
980     * <pre>
981     * StringSubstitutor.createInterpolator().replace("... ${xml:com/domain/document.xml:/path/to/node} ..."));
982     * </pre>
983     * <p>
984     * The above examples convert {@code "com/domain/document.xml:/path/to/node"} to the value of the XPath in the XML
985     * document.
986     * </p>
987     *
988     * @return The XmlStringLookup singleton instance.
989     * @since 1.5
990     */
991    public StringLookup xmlStringLookup() {
992        return XmlStringLookup.INSTANCE;
993    }
994
995}