/* * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2023, Alibaba Group Holding Limited. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.util; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.StringTemplate.Processor; import java.lang.StringTemplate.Processor.Linkage; import jdk.internal.javac.PreviewFeature; /** * This {@link Processor} constructs a {@link String} result using * {@link Formatter} specifications and values found in the {@link StringTemplate}. * Unlike {@link Formatter}, {@link FormatProcessor} uses the value from the * embedded expression that immediately follows, without whitespace, the * format specifier. * For example: * {@snippet : * FormatProcessor fmt = FormatProcessor.create(Locale.ROOT); * int x = 10; * int y = 20; * String result = fmt."%05d\{x} + %05d\{y} = %05d\{x + y}"; * } * In the above example, the value of {@code result} will be {@code "00010 + 00020 = 00030"}. *
* Embedded expressions without a preceeding format specifier, use {@code %s} * by default. * {@snippet : * FormatProcessor fmt = FormatProcessor.create(Locale.ROOT); * int x = 10; * int y = 20; * String result1 = fmt."\{x} + \{y} = \{x + y}"; * String result2 = fmt."%s\{x} + %s\{y} = %s\{x + y}"; * } * In the above example, the value of {@code result1} and {@code result2} will * both be {@code "10 + 20 = 30"}. *
* The {@link FormatProcessor} format specification used and exceptions thrown are the * same as those of {@link Formatter}. *
* However, there are two significant differences related to the position of arguments. * An explict {@code n$} and relative {@code <} index will cause an exception due to * a missing argument list. * Whitespace appearing between the specification and the embedded expression will * also cause an exception. *
* {@link FormatProcessor} allows the use of different locales. For example: * {@snippet : * Locale locale = Locale.forLanguageTag("th-TH-u-nu-thai"); * FormatProcessor thaiFMT = FormatProcessor.create(locale); * int x = 10; * int y = 20; * String result = thaiFMT."%4d\{x} + %4d\{y} = %5d\{x + y}"; * } * In the above example, the value of {@code result} will be * {@code " \u0E51\u0E50 + \u0E52\u0E50 = \u0E53\u0E50"}. *
* For day to day use, the predefined {@link FormatProcessor#FMT} {@link FormatProcessor}
* is available. {@link FormatProcessor#FMT} is defined using the {@link Locale#ROOT}.
* Example: {@snippet :
* int x = 10;
* int y = 20;
* String result = FMT."0x%04x\{x} + 0x%04x\{y} = 0x%04x\{x + y}"; // @highlight substring="FMT"
* }
* In the above example, the value of {@code result} will be {@code "0x000a + 0x0014 = 0x001E"}.
*
* @since 21
*
* @see Processor
*/
@PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
public final class FormatProcessor implements Processor
* If an embedded expression is not immediately preceded by a
* specifier then a {@code %s} is inserted in the format.
*
* @param stringTemplate a {@link StringTemplate} instance
*
* @return constructed {@link String}
* @throws IllegalFormatException
* If a format specifier contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* a specifier not followed immediately by an embedded expression or
* other illegal conditions. For specification of all possible
* formatting errors, see the
* details
* section of the formatter class specification.
* @throws NullPointerException if stringTemplate is null
*
* @see java.util.Formatter
*/
@Override
public final String process(StringTemplate stringTemplate) {
Objects.requireNonNull(stringTemplate);
String format = stringTemplateFormat(stringTemplate.fragments());
Object[] values = stringTemplate.values().toArray();
return new Formatter(locale).format(format, values).toString();
}
/**
* Constructs a {@link MethodHandle} that when supplied with the values from
* a {@link StringTemplate} will produce a result equivalent to that provided by
* {@link FormatProcessor#process(StringTemplate)}. This {@link MethodHandle}
* is used by {@link FormatProcessor#FMT} and the ilk to perform a more
* specialized composition of a result. This specialization is done by
* prescanning the fragments and value types of a {@link StringTemplate}.
*
* Process template expressions can be specialized when the processor is
* of type {@link Linkage} and fetched from a static constant as is
* {@link FormatProcessor#FMT} ({@code static final FormatProcessor}).
*
* Other {@link FormatProcessor FormatProcessors} can be specialized when stored in a static
* final.
* For example:
* {@snippet :
* FormatProcessor THAI_FMT = FormatProcessor.create(Locale.forLanguageTag("th-TH-u-nu-thai"));
* }
* {@code THAI_FMT} will now produce specialized {@link MethodHandle MethodHandles} by way
* of {@link FormatProcessor#linkage(List, MethodType)}.
*
* See {@link FormatProcessor#process(StringTemplate)} for more information.
*
* @throws IllegalFormatException
* If a format specifier contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* a specifier not followed immediately by an embedded expression or
* other illegal conditions. For specification of all possible
* formatting errors, see the
* details
* section of the formatter class specification.
* @throws NullPointerException if fragments or type is null
*
* @see java.util.Formatter
*/
@Override
public MethodHandle linkage(List