-
Notifications
You must be signed in to change notification settings - Fork 65
String Templating
For the most common use case, you can define a string format to be reused througout a class:
private static final StringFormat BUCKET_RESOURCE_NAME =
new StringFormat("projects/{project}/locations/{location}/buckets/{bucket}");
...
// 200 lines away
String bucketResourceName = BUCKET_RESOURCE_NAME.format(projectId, location, bucket);
Or a public format with placeholders to be shared across files:
public final class ResourceNameFormats {
public static final String BUCKET_FORMAT =
"projects/{project}/locations/{location}/buckets/{bucket}";
}
// Another package, another file
String bucketResourceName =
StringFormat.using(ResourceNameFormats.BUCKET_FORMAT, projectId, location, bucket);
In both cases, it's strongly recommended to use the mug-errorprone
compile-time plugin alongside ErrorProne with its rich set of compile-time checks to protect yourself from mistakenly passing the arguments in the wrong order (or passing the wrong thing).
For example the compile-time check will make sure that you pass projectId
or project.id()
or foo.getProject()
for the {project}
placeholder. If you instead passed pageId
in the place of project
, or passed the 3 placeholder values in the wrong order, you'll get a compilation error.
StringFormat
also supports templating into non-String types, as inspired by JEP 459. It allows extensions to be built with custom interpolation rules to create arbitrary types off of a string template.
For example the SafeQuery
class is a SQL templating engine built on top of StringFormat
. It guards against SQL injection; and at the same time the ErrorProne compile-time checks for correct argument ordering works for all extensions including SafeQuery
:
SafeQuery.of("select {columns} from tbl where id = '{id}'", columns, userId)
JEP 459 and following revisions will add string templating to the language sooner or later.
The syntax will likely look like "Hello \{audience}, today is \{day}."
There may be slight variants to the placeholder whether it's \{placeholder}
, or ${placeholder}
or perhaps there is a prefix ahead of the double quote. And there may be a "processor", or not. Hard to say.
But one thing is certain: we'll be able to interpolate variables into strings.
That begs the question: if official templating is so close, is StringFormat.Template
still needed?
It looks like the main benefit of StringFormat
template won't be provided by the JEP. That is: to be able to reuse a template with compile-time protection against incorrect placeholder order.
With the JEP, you can't define a bunch of templates (like official user agent patterns, important user-facing messages) and reuse them in different places. The placeholders must be variables in scope. You could wrap them in methods with parameters. But then you risk the parameters being passed in the wrong order. If the template has many placeholders, it becomes the method with many parameters anti-pattern.
Named parameters, if ever added to the language, when combined with the StringTemplate JEP should supersede StringFormat
.