Class StringFormat

java.lang.Object
com.google.mu.util.StringFormat

public final class StringFormat extends Object
A string parser to extract placeholder values from input strings according to a format string. For example:

 return new StringFormat("{address}+{subaddress}@{domain}")
     .parse("my-ldap+test@google.com", (address, subaddress, domain) -> ...);
 

An ErrorProne check is provided to guard against incorrect lambda parameters to the parse(), parseOrThrow(), parseGreedy() and scan() methods. Both the number of parameters and the lambda parameter names are checked to ensure they match the format string. The arguments passed to the format are also checked. If you use bazel, the check is automatically enforced.

Starting from 6.7, if a certain placeholder is uninteresting and you'd rather not name it, you can use the special ... placeholder and then you won't need to assign a lambda variable to capture it:


 return new StringFormat("{...}+{subaddress}@{domain}")
     .parse("my-ldap+test@google.com", (subaddress, domain) -> ...);
 

Note that except the placeholders, characters in the format string are treated as literals. This works better if your pattern is close to free-form text with characters like '.', '?', '(', '|' and whatnot because you don't need to escape them. On the other hand, the literal characters won't offer regex functionalities you get from (\w+), (foo|bar) etc.

In the face of ambiguity, the parse() methods can be lossy. Consider the format string of String.format("I bought %s and %s", "apples and oranges", "chips"), it returns "I bought apples and oranges and chips"; but the following parsing code will incorrectly parse "apples" as "{fruits}" and "oranges and chips" as "{snacks}":


 new StringFormat("I bought {fruits} and {snacks}")
     .parse("I bought apples and oranges and chips", (fruits, snacks) -> ...);
 
As such, only use this class on trusted input strings (i.e. not user inputs). And use regex instead to better deal with ambiguity.

All the parse() methods attempt to match the entire input string from beginning to end. If you need to find the string format as a substring anywhere inside the input string, or need to find repeated occurrences from the input string, use the scan() methods instead. Tack on .findFirst() on the returned lazy stream if you only care to find a single occurrence.

This class is immutable and pre-compiles the format string at constructor time so that the parse() and scan() methods will be more efficient.

Since:
6.6
  • Constructor Details

    • StringFormat

      public StringFormat(String format)
      Constructs a StringFormat with placeholders in the syntax of "{foo}". For example:
      
       new StringFormat("Dear {customer}, your confirmation number is {conf#}");
       

      Nesting "{placeholder}" syntax inside literal curly braces is supported. For example, you could use a format like: "{name: {name}, age: {age}}", and it will be able to parse record-like strings such as "{name: Joe, age: 25}".

      Parameters:
      format - the template format with placeholders
      Throws:
      IllegalArgumentException - if format is invalid (e.g. a placeholder immediately followed by another placeholder)
  • Method Details

    • using

      @TemplateFormatMethod public static String using(@TemplateString String template, Object... args)
      Returns string with the "{placeholder}"s in template filled by args, in order.

      In the not-so-distant future when string interpolation is supported, you'll unlikely need String.format() or third-party templating. But you could still need to define some public template constants to be reused among multiple classes. For example:

      
       throw new ApiException(
           StringFormat.with(StandardErrors.ACCOUNT_LOCKED, accountId, waitTime));
       

      StringFormat.with("{foo}={bar}", foo, bar) is equivalent to new StringFormat("{foo}={bar}").format(foo, bar) except that it's twice as fast and syntactically shorter when the format string is inlined as opposed to being stored as a constant StringFormat object.

      Compared to equivalent String.format("%s=%s", foo, bar), using named placeholders works better if the template strings are public constants that are used across multiple classes. The compile-time placeholder name check helps to ensure that the arguments are passed correctly.

      Among the different formatting APIs, in the order of efficiency (fastest first):

      1. FORMAT_CONSTANT.format(...).
      2. StringFormat.using(...) and String.format(...) in Java 21.
      3. new StringFormat("{foo}={bar}").format(...).
      4. String.format(...) in Java 11
      Since:
      8.0
    • span

      public static Substring.Pattern span(String format)
      Returns a Substring.Pattern spanning the substring matching format. For example, StringFormat.span("projects/{project}/") is equivalent to spanningInOrder("projects/", "/").

      Useful if you need a Substring.Pattern for purposes such as composition, but prefer a more self-documenting syntax. The placeholder names in the format string don't affect runtime semantics, but using meaningful names improves readability.

      Since:
      7.0
    • to

      public static <T> StringFormat.Template<T> to(Function<? super String,? extends T> creator, String format)
      Returns a factory of type T using format string as the template, whose curly-braced placeholders will be filled with the template arguments and then passed to the creator function to create the T instances.

      A typical use case is to pre-create an exception template that can be used to create exceptions filled with different parameter values. For example:

      
       private static final StringFormat.Template<IOException> JOB_FAILED =
           StringFormat.to(
               IOException::new, "Job ({job_id}) failed with {error_code}, details: {details}");
      
         // 150 lines later.
         // Compile-time enforced that parameters are correct and in the right order.
         throw JOB_FAILED.with(jobId, errorCode, errorDetails);
       
      Since:
      7.0
    • template

      public static <T> StringFormat.Template<T> template(String template, StringFormat.Interpolator<? extends T> interpolator)
      Returns a go/jep-430 style template of T produced by interpolating arguments into the template string, using the given interpolator function.

      The interpolator function is an SPI. That is, instead of users creating the lambda in-line, you are expected to provide a canned implementation -- typically by wrapping it inside a convenient facade class. For example:

      
       // Provided to the user:
       public final class BigQuery {
         public static Template<QueryRequest> template(String template) {
           return StringFormat.template(template, (fragments, placeholders) -> ...);
         }
       }
      
       // At call site:
       private static final Template<QueryRequest> GET_CASE_BY_ID = BigQuery.template(
           "SELECT CaseId, Description FROM tbl WHERE CaseId = '{case_id}'");
      
          ....
          QueryRequest query = GET_CASE_BY_ID.with(caseId);  // automatically escape special chars
       

      This way, the StringFormat API provides compile-time safety, and the SPI plugs in custom interpolation logic.

      Calling StringFormat.Template.with(java.lang.Object...) with unexpected number of parameters will throw IllegalArgumentException without invoking interpolator.

      Since:
      7.0
    • parse

      public final <R> Optional<R> parse(String input, Function<? super String,? extends R> mapper)
      Parses input and applies the mapper function with the single placeholder value in this string format.

      For example:

      
       new StringFormat("Job failed (job id: {job_id})").parse(input, jobId -> ...);
       
      Returns:
      the return value of the mapper function if not null. Returns empty if input doesn't match the format, or mapper returns null.
      Throws:
      IllegalArgumentException - if or the format string doesn't have exactly one placeholder.
    • parse

      public final <R> Optional<R> parse(String input, BiFunction<? super String,? super String,? extends R> mapper)
      Parses input and applies mapper with the two placeholder values in this string format.

      For example:

      
       new StringFormat("Job failed (job id: '{id}', error code: {code})")
           .parse(input, (jobId, errorCode) -> ...);
       
      Returns:
      the return value of the mapper function if not null. Returns empty if input doesn't match the format, or mapper returns null.
      Throws:
      IllegalArgumentException - if or the format string doesn't have exactly two placeholders.
    • parse

      public final <R> Optional<R> parse(String input, MapFrom3<? super String,? extends R> mapper)
      Similar to parse(String, BiFunction), but parses input and applies mapper with the 3 placeholder values in this string format.

      For example:

      
       new StringFormat("Job failed (job id: '{job_id}', error code: {code}, error details: {details})")
           .parse(input, (jobId, errorCode, errorDetails) -> ...);
       
      Returns:
      the return value of the mapper function if not null. Returns empty if input doesn't match the format, or mapper returns null.
      Throws:
      IllegalArgumentException - if or the format string doesn't have exactly 3 placeholders.
    • parse

      public final <R> Optional<R> parse(String input, MapFrom4<? super String,? extends R> mapper)
      Similar to parse(String, BiFunction), but parses input and applies mapper with the 4 placeholder values in this string format.
      Returns:
      the return value of the mapper function if not null. Returns empty if input doesn't match the format, or mapper returns null.
      Throws:
      IllegalArgumentException - if or the format string doesn't have exactly 4 placeholders.
    • parse

      public final <R> Optional<R> parse(String input, MapFrom5<? super String,? extends R> mapper)
      Similar to parse(String, BiFunction), but parses input and applies mapper with the 5 placeholder values in this string format.
      Returns:
      the return value of the mapper function if not null. Returns empty if input doesn't match the format, or mapper returns null.
      Throws:
      IllegalArgumentException - if or the format string doesn't have exactly 5 placeholders.
    • parse

      public final <R> Optional<R> parse(String input, MapFrom6<? super String,? extends R> mapper)
      Similar to parse(String, BiFunction), but parses input and applies mapper with the 6 placeholder values in this string format.
      Returns:
      the return value of the mapper function if not null. Returns empty if input doesn't match the format, or mapper returns null.
      Throws:
      IllegalArgumentException - if or the format string doesn't have exactly 6 placeholders.
    • parse

      public final <R> Optional<R> parse(String input, MapFrom7<? super String,? extends R> mapper)
      Similar to parse(String, BiFunction), but parses input and applies mapper with the 7 placeholder values in this string format.
      Returns:
      the return value of the mapper function if not null. Returns empty if input doesn't match the format, or mapper returns null.
      Throws:
      IllegalArgumentException - if or the format string doesn't have exactly 7 placeholders.
      Since:
      7.2
    • parse

      public final <R> Optional<R> parse(String input, MapFrom8<? super String,? extends R> mapper)
      Similar to parse(String, BiFunction), but parses input and applies mapper with the 8 placeholder values in this string format.
      Returns:
      the return value of the mapper function if not null. Returns empty if input doesn't match the format, or mapper returns null.
      Throws:
      IllegalArgumentException - if or the format string doesn't have exactly 8 placeholders.
      Since:
      7.2
    • parse

      public final Optional<List<Substring.Match>> parse(String input)
      Parses input against the pattern.

      Returns an immutable list of placeholder values in the same order as the placeholders in the format string, upon success; otherwise returns empty.

      The Substring.Match result type allows caller to inspect the characters around each match, or to access the raw index in the input string.

    • parseOrThrow

      public final <R> R parseOrThrow(String input, Function<? super String,R> mapper)
      Parses input and applies mapper with the single placeholder value in this format string.

      For example:

      
       new StringFormat("Job failed (job id: {job_id})").parseOrThrow(input, jobId -> ...);
       

      Unlike parse(String, Function), IllegalArgumentException is thrown if the input string doesn't match the string format. The error message will include both the input string and the format string for ease of debugging, but is otherwise generic. If you need a different exception type, or need to customize the error message, consider using AbstractStringFormat.<R>parse(java.lang.String,java.util.function.Function<? super java.lang.String,? extends R>) instead and call Optional.orElseThrow() explicitly.

      Returns:
      the return value of the mapper function if not null. Returns empty if input doesn't match the format, or mapper returns null.
      Throws:
      IllegalArgumentException - if the input string doesn't match the string format, or if the format string doesn't have exactly one placeholder
      NullPointerException - if any of the parameter is null or mapper returns null.
      Since:
      7.0
    • parseOrThrow

      public final <R> R parseOrThrow(String input, BiFunction<? super String,? super String,R> mapper)
      Parses input and applies mapper with the two placeholder values in this format string.

      For example:

      
       new StringFormat("Job failed (job id: '{job_id}', error code: {error_code})")
           .parseOrThrow(input, (jobId, errorCode) -> ...);
       

      Unlike parse(String, BiFunction), IllegalArgumentException is thrown if the input string doesn't match the string format. The error message will include both the input string and the format string for ease of debugging, but is otherwise generic. If you need a different exception type, or need to customize the error message, consider using AbstractStringFormat.<R>parse(java.lang.String,java.util.function.BiFunction<? super java.lang.String,? super java.lang.String,? extends R>) instead and call Optional.orElseThrow() explicitly.

      Returns:
      the return value of the mapper function applied on the extracted placeholder value.
      Throws:
      IllegalArgumentException - if the input string doesn't match the string format, or if the format string doesn't have exactly two placeholders
      NullPointerException - if any of the parameter is null or mapper returns null.
      Since:
      7.0
    • parseOrThrow

      public final <R> R parseOrThrow(String input, MapFrom3<? super String,R> mapper)
      Similar to parseOrThrow(String, BiFunction), but parses input and applies mapper with the 3 placeholder values in this format string.

      For example:

      
       new StringFormat("Job failed (id: '{job_id}', code: {error_code}, error details: {details})")
           .parseOrThrow(input, (jobId, errorCode, errorDetails) -> ...);
       

      Unlike parse(String, MapFrom3), IllegalArgumentException is thrown if the input string doesn't match the string format. The error message will include both the input string and the format string for ease of debugging, but is otherwise generic. If you need a different exception type, or need to customize the error message, consider using AbstractStringFormat.<R>parse(java.lang.String,com.google.mu.function.MapFrom3<? super java.lang.String,? extends R>) instead and call Optional.orElseThrow() explicitly.

      Returns:
      the return value of the mapper function applied on the extracted placeholder values.
      Throws:
      IllegalArgumentException - if the input string doesn't match the string format, or if the format string doesn't have exactly 3 placeholders
      NullPointerException - if any of the parameter is null or mapper returns null.
      Since:
      7.0
    • parseOrThrow

      public final <R> R parseOrThrow(String input, MapFrom4<? super String,R> mapper)
      Similar to parseOrThrow(String, BiFunction), but parses input and applies mapper with the 4 placeholder values in this string format.

      Unlike parse(String, MapFrom4), IllegalArgumentException is thrown if the input string doesn't match the string format. The error message will include both the input string and the format string for ease of debugging, but is otherwise generic. If you need a different exception type, or need to customize the error message, consider using AbstractStringFormat.<R>parse(java.lang.String,com.google.mu.function.MapFrom4<? super java.lang.String,? extends R>) instead and call Optional.orElseThrow() explicitly.

      Returns:
      the return value of the mapper function applied on the extracted placeholder values.
      Throws:
      IllegalArgumentException - if the input string doesn't match the string format, or if the format string doesn't have exactly 4 placeholders
      NullPointerException - if any of the parameter is null or mapper returns null.
      Since:
      7.0
    • parseOrThrow

      public final <R> R parseOrThrow(String input, MapFrom5<? super String,R> mapper)
      Similar to parseOrThrow(String, BiFunction), but parses input and applies mapper with the 5 placeholder values in this string format.

      Unlike parse(String, MapFrom5), IllegalArgumentException is thrown if the input string doesn't match the string format. The error message will include both the input string and the format string for ease of debugging, but is otherwise generic. If you need a different exception type, or need to customize the error message, consider using AbstractStringFormat.<R>parse(java.lang.String,com.google.mu.function.MapFrom5<? super java.lang.String,? extends R>) instead and call Optional.orElseThrow() explicitly.

      Returns:
      the return value of the mapper function applied on the extracted placeholder values.
      Throws:
      IllegalArgumentException - if the input string doesn't match the string format, or if the format string doesn't have exactly 5 placeholders
      NullPointerException - if any of the parameter is null or mapper returns null.
      Since:
      7.0
    • parseOrThrow

      public final <R> R parseOrThrow(String input, MapFrom6<? super String,R> mapper)
      Similar to parseOrThrow(String, BiFunction), but parses input and applies mapper with the 6 placeholder values in this string format.

      Unlike parse(String, MapFrom6), IllegalArgumentException is thrown if the input string doesn't match the string format. The error message will include both the input string and the format string for ease of debugging, but is otherwise generic. If you need a different exception type, or need to customize the error message, consider using AbstractStringFormat.<R>parse(java.lang.String,com.google.mu.function.MapFrom6<? super java.lang.String,? extends R>) instead and call Optional.orElseThrow() explicitly.

      Returns:
      the return value of the mapper function applied on the extracted placeholder values.
      Throws:
      IllegalArgumentException - if the input string doesn't match the string format, or if the format string doesn't have exactly 6 placeholders
      NullPointerException - if any of the parameter is null or mapper returns null.
      Since:
      7.0
    • parseOrThrow

      public final <R> R parseOrThrow(String input, MapFrom7<? super String,R> mapper)
      Similar to parseOrThrow(String, BiFunction), but parses input and applies mapper with the 7 placeholder values in this string format.

      Unlike parse(String, MapFrom6), IllegalArgumentException is thrown if the input string doesn't match the string format. The error message will include both the input string and the format string for ease of debugging, but is otherwise generic. If you need a different exception type, or need to customize the error message, consider using AbstractStringFormat.<R>parse(java.lang.String,com.google.mu.function.MapFrom6<? super java.lang.String,? extends R>) instead and call Optional.orElseThrow() explicitly.

      Returns:
      the return value of the mapper function applied on the extracted placeholder values.
      Throws:
      IllegalArgumentException - if the input string doesn't match the string format, or if the format string doesn't have exactly 7 placeholders
      NullPointerException - if any of the parameter is null or mapper returns null.
      Since:
      7.2
    • parseOrThrow

      public final <R> R parseOrThrow(String input, MapFrom8<? super String,R> mapper)
      Similar to parseOrThrow(String, BiFunction), but parses input and applies mapper with the 8 placeholder values in this string format.

      Unlike parse(String, MapFrom6), IllegalArgumentException is thrown if the input string doesn't match the string format. The error message will include both the input string and the format string for ease of debugging, but is otherwise generic. If you need a different exception type, or need to customize the error message, consider using AbstractStringFormat.<R>parse(java.lang.String,com.google.mu.function.MapFrom6<? super java.lang.String,? extends R>) instead and call Optional.orElseThrow() explicitly.

      Returns:
      the return value of the mapper function applied on the extracted placeholder values.
      Throws:
      IllegalArgumentException - if the input string doesn't match the string format, or if the format string doesn't have exactly 8 placeholders
      NullPointerException - if any of the parameter is null or mapper returns null.
      Since:
      7.2
    • parseGreedy

      public final <R> Optional<R> parseGreedy(String input, Function<? super String,? extends R> mapper)
      Similar to parse(String, Function), parses input and applies mapper with the single placeholder value in this format string, but matches the placeholders backwards from the end to the beginning of the input string.

      For unambiguous strings, it's equivalent to parse(String, Function), but if for example you are parsing "a/b/c" against the pattern of "{parent}/{...}", parse("a/b/c", parent -> parent) results in "a", while parseGreedy("a/b/c", parent -> parent) results in "a/b".

      This is also equivalent to allowing the left placeholder to match greedily, while still requiring the remaining placeholder(s) to be matched.

      Returns:
      the return value of the mapper function if not null. Returns empty if input doesn't match the format, or mapper returns null.
      Throws:
      IllegalArgumentException - if the format string doesn't have exactly one placeholder.
      Since:
      7.0
    • parseGreedy

      public final <R> Optional<R> parseGreedy(String input, BiFunction<? super String,? super String,? extends R> mapper)
      Similar to parse(String, BiFunction), parses input and applies mapper with the two placeholder values in this format string, but matches the placeholders backwards from the end to the beginning of the input string.

      For unambiguous strings, it's equivalent to parse(String, BiFunction), but if for example you are parsing "a/b/c" against the pattern of "{parent}/{child}", parse("a/b/c", (parent, child) -> ...) parses out "a" as parent and "b/c" as child, while parseGreedy("a/b/c", (parent, child) -> ...) parses "a/b" as parent and "c" as child.

      This is also equivalent to allowing the left placeholder to match greedily, while still requiring the remaining placeholder(s) to be matched.

      Returns:
      the return value of the mapper function if not null. Returns empty if input doesn't match the format, or mapper returns null.
      Throws:
      IllegalArgumentException - if the format string doesn't have exactly two placeholders.
      Since:
      7.0
    • parseGreedy

      public final <R> Optional<R> parseGreedy(String input, MapFrom3<? super String,? extends R> mapper)
      Similar to parse(String, MapFrom3), parses input and applies mapper with the 3 placeholder values in this format string, but matches the placeholders backwards from the end to the beginning of the input string.

      This is also equivalent to allowing the left placeholder to match greedily, while still requiring the remaining placeholder(s) to be matched.

      Returns:
      the return value of the mapper function if not null. Returns empty if input doesn't match the format, or mapper returns null.
      Throws:
      IllegalArgumentException - if the format string doesn't have exactly 3 placeholders.
      Since:
      7.0
    • parseGreedy

      public final <R> Optional<R> parseGreedy(String input, MapFrom4<? super String,? extends R> mapper)
      Similar to parse(String, MapFrom4), parses input and applies mapper with the 3 placeholder values in this format string, but matches the placeholders backwards from the end to the beginning of the input string.

      This is also equivalent to allowing the left placeholder to match greedily, while still requiring the remaining placeholder(s) to be matched.

      Returns:
      the return value of the mapper function if not null. Returns empty if input doesn't match the format, or mapper returns null.
      Throws:
      IllegalArgumentException - if the format string doesn't have exactly 4 placeholders.
      Since:
      7.0
    • parseGreedy

      public final <R> Optional<R> parseGreedy(String input, MapFrom5<? super String,? extends R> mapper)
      Similar to parse(String, MapFrom5), parses input and applies mapper with the 5 placeholder values in this format string, but matches the placeholders backwards from the end to the beginning of the input string.

      This is also equivalent to allowing the left placeholder to match greedily, while still requiring the remaining placeholder(s) to be matched.

      Returns:
      the return value of the mapper function if not null. Returns empty if input doesn't match the format, or mapper returns null.
      Throws:
      IllegalArgumentException - if the format string doesn't have exactly 5 placeholders.
      Since:
      7.0
    • matches

      public final boolean matches(String input)
      Returns true if this format matches input entirely.
      Since:
      7.0
    • replaceAllFrom

      public final String replaceAllFrom(String input, Function<? super Substring.Match,?> replacement)
      Scans input and replaces all matches using the replacement function.

      Note that while the placeholder value(s) are passed to the replacement function, the full matching substring of the string format (including but not limited to the placeholders) are replaced by the return value of the replacement function. So for example if you are trying to rewrite every "<{value}>" to "<v...>", be sure to include the angle bracket characters as in:

      
       StringFormat bracketed = new StringFormat(""<{value}>"");
       String rewritten =
           bracketed.replaceAllFrom(input, value -> bracketed.format(value.charAt(0) + "..."));
       

      If no match is found, the input string is returned.

      If replacement returns null, the match is ignored as if it didn't match the format. This can be used to post-filter the match with custom predicates (e.g. a placeholder value must be digits only).

      The replacement function accepts Substring.Match instead of String to avoid unnecessary copying of the characters. If you are passing in a method reference, it can also take CharSequence or Object as the parameter type.

      Throws:
      IllegalArgumentException - if the format string doesn't have exactly 1 named placeholder
      Since:
      7.2
    • replaceAllFrom

      public final String replaceAllFrom(String input, BiFunction<? super Substring.Match,? super Substring.Match,?> replacement)
      Scans input and replaces all matches using the replacement function.

      Note that while the placeholder value(s) are passed to the replacement function, the full matching substring of the string format (including but not limited to the placeholders) are replaced by the return value of the replacement function. So for example if you are trying to rewrite every "[{key}:{value}]" to "[{key}={value}]", be sure to include the square bracket characters as in:

      
       StringFormat oldFormat = new StringFormat("[{key}:{value}]");
       StringFormat newFormat = new StringFormat("[{key}={value}]");
       String rewritten =
           oldFormat.replaceAllFrom(input, (key, value) -> newFormat.format(key, value));
       

      If no match is found, the input string is returned.

      If replacement returns null, the match is ignored as if it didn't match the format. This can be used to post-filter the match with custom predicates (e.g. a placeholder value must be digits only).

      The replacement function accepts Substring.Match instead of String to avoid unnecessary copying of the characters. If you are passing in a method reference, it can also take CharSequence or Object as the parameter types.

      Throws:
      IllegalArgumentException - if the format string doesn't have exactly 2 named placeholder
      Since:
      7.2
    • replaceAllFrom

      public final String replaceAllFrom(String input, MapFrom3<? super Substring.Match,?> replacement)
      Scans input and replaces all matches using the replacement function.

      If no match is found, the input string is returned.

      If replacement returns null, the match is ignored as if it didn't match the format. This can be used to post-filter the match with custom predicates (e.g. a placeholder value must be digits only).

      The replacement function accepts Substring.Match instead of String to avoid unnecessary copying of the characters. If you are passing in a method reference, it can also take CharSequence or Object as the parameter types.

      Throws:
      IllegalArgumentException - if the format string doesn't have exactly 3 named placeholder
      Since:
      7.2
    • replaceAllFrom

      public final String replaceAllFrom(String input, MapFrom4<? super Substring.Match,?> replacement)
      Scans input and replaces all matches using the replacement function.

      If no match is found, the input string is returned.

      If replacement returns null, the match is ignored as if it didn't match the format. This can be used to post-filter the match with custom predicates (e.g. a placeholder value must be digits only).

      The replacement function accepts Substring.Match instead of String to avoid unnecessary copying of the characters. If you are passing in a method reference, it can also take CharSequence or Object as the parameter types.

      Throws:
      IllegalArgumentException - if the format string doesn't have exactly 4 named placeholder
      Since:
      7.2
    • replaceAllFrom

      public final String replaceAllFrom(String input, MapFrom5<? super Substring.Match,?> replacement)
      Scans input and replaces all matches using the replacement function.

      If no match is found, the input string is returned.

      If replacement returns null, the match is ignored as if it didn't match the format. This can be used to post-filter the match with custom predicates (e.g. a placeholder value must be digits only).

      The replacement function accepts Substring.Match instead of String to avoid unnecessary copying of the characters. If you are passing in a method reference, it can also take CharSequence or Object as the parameter types.

      Throws:
      IllegalArgumentException - if the format string doesn't have exactly 5 named placeholder
      Since:
      7.2
    • replaceAllFrom

      public final String replaceAllFrom(String input, MapFrom6<? super Substring.Match,?> replacement)
      Scans input and replaces all matches using the replacement function.

      If no match is found, the input string is returned.

      If replacement returns null, the match is ignored as if it didn't match the format. This can be used to post-filter the match with custom predicates (e.g. a placeholder value must be digits only).

      The replacement function accepts Substring.Match instead of String to avoid unnecessary copying of the characters. If you are passing in a method reference, it can also take CharSequence or Object as the parameter types.

      Throws:
      IllegalArgumentException - if the format string doesn't have exactly 6 named placeholder
      Since:
      7.2
    • replaceAllFrom

      public final String replaceAllFrom(String input, MapFrom7<? super Substring.Match,?> replacement)
      Scans input and replaces all matches using the replacement function.

      If no match is found, the input string is returned.

      If replacement returns null, the match is ignored as if it didn't match the format. This can be used to post-filter the match with custom predicates (e.g. a placeholder value must be digits only).

      The replacement function accepts Substring.Match instead of String to avoid unnecessary copying of the characters. If you are passing in a method reference, it can also take CharSequence or Object as the parameter types.

      Throws:
      IllegalArgumentException - if the format string doesn't have exactly 7 named placeholder
      Since:
      7.2
    • replaceAllFrom

      public final String replaceAllFrom(String input, MapFrom8<? super Substring.Match,?> replacement)
      Scans input and replaces all matches using the replacement function.

      If no match is found, the input string is returned.

      If replacement returns null, the match is ignored as if it didn't match the format. This can be used to post-filter the match with custom predicates (e.g. a placeholder value must be digits only).

      The replacement function accepts Substring.Match instead of String to avoid unnecessary copying of the characters. If you are passing in a method reference, it can also take CharSequence or Object as the parameter types.

      Throws:
      IllegalArgumentException - if the format string doesn't have exactly 8 named placeholder
      Since:
      7.2
    • scan

      public final Stream<List<Substring.Match>> scan(String input)
      Scans the input string and extracts all matched placeholders in this string format.

      unlike parse(String), the input string isn't matched entirely: the pattern doesn't have to start from the beginning, and if there are some remaining characters that don't match the pattern any more, the stream stops. In particular, if there is no match, empty stream is returned.

    • scan

      public final <R> Stream<R> scan(String input, Function<? super String,? extends R> mapper)
      Scans the input string and extracts all matches of this string format. Returns the lazy stream of non-null results from passing the single placeholder values to the mapper function for each iteration, with null results skipped.

      For example:

      
       new StringFormat("/home/usr/myname/{file_name}\n")
           .scan(multiLineInput, fileName -> ...);
       

      unlike parse(String, Function), the input string isn't matched entirely: the pattern doesn't have to start from the beginning, and if there are some remaining characters that don't match the pattern any more, the stream stops. In particular, if there is no match, empty stream is returned.

      By default, placeholders are allowed to be matched against an empty string. If the placeholder isn't expected to be empty, consider filtering it out by returning null from the mapper function, which will then be ignored in the result stream.

    • scan

      public final <R> Stream<R> scan(String input, BiFunction<? super String,? super String,? extends R> mapper)
      Scans the input string and extracts all matches of this string format. Returns the lazy stream of non-null results from passing the two placeholder values to the mapper function for each iteration, with null results skipped.

      For example:

      
       new StringFormat("[key={key}, value={value}]")
           .repeatedly()
           .parse(input, (key, value) -> ...);
       

      unlike parse(String, BiFunction), the input string isn't matched entirely: the pattern doesn't have to start from the beginning, and if there are some remaining characters that don't match the pattern any more, the stream stops. In particular, if there is no match, empty stream is returned.

      By default, placeholders are allowed to be matched against an empty string. If a certain placeholder isn't expected to be empty, consider filtering it out by returning null from the mapper function, which will then be ignored in the result stream.

    • scan

      public final <R> Stream<R> scan(String input, MapFrom3<? super String,? extends R> mapper)
      Scans the input string and extracts all matches of this string format. Returns the lazy stream of non-null results from passing the 3 placeholder values to the mapper function for each iteration, with null results skipped.

      For example:

      
       new StringFormat("[{lhs} + {rhs} = {result}]")
           .repeatedly()
           .parse(input, (lhs, rhs, result) -> ...);
       

      unlike parse(String, MapFrom3), the input string isn't matched entirely: the pattern doesn't have to start from the beginning, and if there are some remaining characters that don't match the pattern any more, the stream stops. In particular, if there is no match, empty stream is returned.

      By default, placeholders are allowed to be matched against an empty string. If a certain placeholder isn't expected to be empty, consider filtering it out by returning null from the mapper function, which will then be ignored in the result stream.

    • scan

      public final <R> Stream<R> scan(String input, MapFrom4<? super String,? extends R> mapper)
      Scans the input string and extracts all matches of this string format. Returns the lazy stream of non-null results from passing the 4 placeholder values to the mapper function for each iteration, with null results skipped.

      unlike parse(String, MapFrom4), the input string isn't matched entirely: the pattern doesn't have to start from the beginning, and if there are some remaining characters that don't match the pattern any more, the stream stops. In particular, if there is no match, empty stream is returned.

      By default, placeholders are allowed to be matched against an empty string. If a certain placeholder isn't expected to be empty, consider filtering it out by returning null from the mapper function, which will then be ignored in the result stream.

    • scan

      public final <R> Stream<R> scan(String input, MapFrom5<? super String,? extends R> mapper)
      Scans the input string and extracts all matches of this string format. Returns the lazy stream of non-null results from passing the 5 placeholder values to the mapper function for each iteration, with null results skipped.

      unlike parse(String, MapFrom5), the input string isn't matched entirely: the pattern doesn't have to start from the beginning, and if there are some remaining characters that don't match the pattern any more, the stream stops. In particular, if there is no match, empty stream is returned.

      By default, placeholders are allowed to be matched against an empty string. If a certain placeholder isn't expected to be empty, consider filtering it out by returning null from the mapper function, which will then be ignored in the result stream.

    • scan

      public final <R> Stream<R> scan(String input, MapFrom6<? super String,? extends R> mapper)
      Scans the input string and extracts all matches of this string format. Returns the lazy stream of non-null results from passing the 6 placeholder values to the mapper function for each iteration, with null results skipped.

      unlike parse(String, MapFrom6), the input string isn't matched entirely: the pattern doesn't have to start from the beginning, and if there are some remaining characters that don't match the pattern any more, the stream stops. In particular, if there is no match, empty stream is returned.

      By default, placeholders are allowed to be matched against an empty string. If a certain placeholder isn't expected to be empty, consider filtering it out by returning null from the mapper function, which will then be ignored in the result stream.

    • scan

      public final <R> Stream<R> scan(String input, MapFrom7<? super String,? extends R> mapper)
      Scans the input string and extracts all matches of this string format. Returns the lazy stream of non-null results from passing the 7 placeholder values to the mapper function for each iteration, with null results skipped.

      unlike parse(String, MapFrom6), the input string isn't matched entirely: the pattern doesn't have to start from the beginning, and if there are some remaining characters that don't match the pattern any more, the stream stops. In particular, if there is no match, empty stream is returned.

      By default, placeholders are allowed to be matched against an empty string. If a certain placeholder isn't expected to be empty, consider filtering it out by returning null from the mapper function, which will then be ignored in the result stream.

      Since:
      7.2
    • scan

      public final <R> Stream<R> scan(String input, MapFrom8<? super String,? extends R> mapper)
      Scans the input string and extracts all matches of this string format. Returns the lazy stream of non-null results from passing the 8 placeholder values to the mapper function for each iteration, with null results skipped.

      unlike parse(String, MapFrom6), the input string isn't matched entirely: the pattern doesn't have to start from the beginning, and if there are some remaining characters that don't match the pattern any more, the stream stops. In particular, if there is no match, empty stream is returned.

      By default, placeholders are allowed to be matched against an empty string. If a certain placeholder isn't expected to be empty, consider filtering it out by returning null from the mapper function, which will then be ignored in the result stream.

      Since:
      7.2
    • scanAndCollectFrom

      public final <R> R scanAndCollectFrom(String input, Collector<? super String,?,R> collector)
      Scans the input string and collects all matches of this string format using collector.

      For example:

      
       List<String> fileNames =
           new StringFormat("/home/usr/myname/{file_name}\n")
               .scanAndCollectFrom(multiLineInput, toList());
       
      Throws:
      IllegalArgumentException - if the format string doesn't have exactly one placeholder.
      Since:
      8.0
    • scanAndCollectFrom

      public final <R> R scanAndCollectFrom(String input, BiCollector<? super String,? super String,R> collector)
      Scans the input string and collects all pairs of placeholders defined by this string format using collector.

      For example:

      
       Map<String, String> keyValues =
           new StringFormat("{{key}: {value}}")
               .scanAndCollectFrom(input, Collectors::toMap);
       

      If you need to apply intermediary operations before collecting to the final result, consider using BiStream::toBiStream like the following code:

      
       ImmutableMap<UserId, EmailAddress> userEmails =
           new StringFormat("{{key}: {value}}")
               .scanAndCollectFrom(input, BiStream::toBiStream)
               .mapKeys(UserId::of)
               .mapValues(EmailAddress::parse)
               .toMap();
       
      Throws:
      IllegalArgumentException - if the format string doesn't have exactly two placeholders.
      Since:
      8.0
    • format

      public final String format(Object... args)
      Returns the string formatted with placeholders filled using args. This is the reverse operation of the parse(...) methods. For example:
      
       new StringFormat("Hello {who}").format("world")
           => "Hello world"
       
      Throws:
      IllegalArgumentException - if the number of arguments doesn't match that of the placeholders
    • toString

      public String toString()
      Returns the string format.
      Overrides:
      toString in class Object