MFFunctionRegistry.java
// © 2022 and later: Unicode, Inc. and others.
// License & terms of use: https://www.unicode.org/copyright.html
package com.ibm.icu.message2;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* This class is used to register mappings between various function names and the factories that can
* create those functions.
*
* <p>For example to add formatting for a {@code Person} object one would need to:
*
* <ul>
* <li>write a function (class, lambda, etc.) that does the formatting proper (implementing {@link
* Function})
* <li>write a factory that creates such a function (implementing {@link FunctionFactory})
* <li>add a mapping from the function name as used in the syntax (for example {@code "person"})
* to the factory
* <li>optionally add a mapping from the class to format ({@code ...Person.class}) to the function
* name ({@code "person"}), so that one can use a placeholder in the message without
* specifying a function (for example {@code "... {$me} ..."} instead of {@code "... {$me
* :person} ..."}, if the class of {@code $me} is an {@code instanceof Person}).
* </ul>
*
* <p><b>NOTE:</b> all function names are normalized to NFC.
*
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public class MFFunctionRegistry {
private final Map<String, FunctionFactory> functionMap;
private final Map<Class<?>, String> classToFunction;
private MFFunctionRegistry(Builder builder) {
this.functionMap = new HashMap<>(builder.functionMap);
this.classToFunction = new HashMap<>(builder.classToFunction);
}
/**
* Creates a builder.
*
* @return the Builder.
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public static Builder builder() {
return new Builder();
}
/**
* Returns the function factory used to create the function named {@code name}.
*
* <p>Note: function name here means the name used to refer to the function in the MessageFormat
* 2 syntax, for example {@code "... {$exp :datetime} ..."}<br>
* The function name here is {@code "datetime"}, and does not have to correspond to the name of
* the methods / classes used to implement the functionality.
*
* <p>For example one might write a {@code PersonFunctionFactory} returning a {@code
* PersonFunction}, and map that to the MessageFormat function named {@code "person"}.<br>
* The only name visible to the users of MessageFormat syntax will be {@code "person"}.
*
* @param functionName the function name.
* @return the factory creating function for {@code name}. Returns {@code null} if none is
* registered.
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public FunctionFactory getFunction(String functionName) {
return functionMap.get(StringUtils.toNfc(functionName));
}
/**
* Get all know names that have a mappings from name to {@link FunctionFactory}.
*
* @return a set of all the known function names.
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public Set<String> getFunctionNames() {
return functionMap.keySet();
}
/**
* Returns the name of the function used to format an object of type {@code clazz}.
*
* @param clazz the class of the object to format.
* @return the name of the function class, if registered. Returns {@code null} otherwise.
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public String getDefaultFunctionNameForType(Class<?> clazz) {
// Search for the class "as is", to save time.
// If we don't find it then we iterate the registered classes and check
// if the class is an instanceof the ones registered.
// For example a BuddhistCalendar when we only registered Calendar
String result = classToFunction.get(clazz);
if (result != null) {
return result;
}
// We didn't find the class registered explicitly "as is"
for (Map.Entry<Class<?>, String> e : classToFunction.entrySet()) {
if (e.getKey().isAssignableFrom(clazz)) {
return e.getValue();
}
}
return null;
}
/**
* Get all know classes that have a mappings from class to function name.
*
* @return a set of all the known classes that have mapping to function names.
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public Set<Class<?>> getDefaultFunctionTypes() {
return classToFunction.keySet();
}
/**
* A {@code Builder} used to build instances of {@link MFFunctionRegistry}.
*
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public static class Builder {
private final Map<String, FunctionFactory> functionMap = new HashMap<>();
private final Map<Class<?>, String> classToFunction = new HashMap<>();
// Prevent direct creation
private Builder() {}
/**
* Adds all the mapping from another registry to this one.
*
* @param functionRegistry the registry to copy from.
* @return the builder, for fluent use.
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public Builder addAll(MFFunctionRegistry functionRegistry) {
functionMap.putAll(functionRegistry.functionMap);
classToFunction.putAll(functionRegistry.classToFunction);
return this;
}
/**
* Adds a mapping from a function name to a {@link FunctionFactory}.
*
* @param functionName the function name (as used in the MessageFormat 2 syntax).
* @param functionFactory the factory that handles the name.
* @return the builder, for fluent use.
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public Builder setFunction(String functionName, FunctionFactory functionFactory) {
functionMap.put(StringUtils.toNfc(functionName), functionFactory);
return this;
}
/**
* Remove the function associated with the name.
*
* @param functionName the name of the function to remove.
* @return the builder, for fluent use.
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public Builder removeFunction(String functionName) {
functionMap.remove(StringUtils.toNfc(functionName));
return this;
}
/**
* Remove all the function mappings.
*
* @return the builder, for fluent use.
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public Builder clearFunctions() {
functionMap.clear();
return this;
}
/**
* Adds a mapping from a type to format to a {@link FunctionFactory} function name.
*
* @param clazz the class of the type to format.
* @param functionName the unction name (as used in the MessageFormat 2 syntax).
* @return the builder, for fluent use.
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public Builder setDefaultFunctionNameForType(Class<?> clazz, String functionName) {
classToFunction.put(clazz, StringUtils.toNfc(functionName));
return this;
}
/**
* Remove the function name associated with the class.
*
* @param clazz the class to remove the mapping for.
* @return the builder, for fluent use.
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public Builder removeDefaultFunctionNameForType(Class<?> clazz) {
classToFunction.remove(clazz);
return this;
}
/**
* Remove all the class to function-names mappings.
*
* @return the builder, for fluent use.
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public Builder clearDefaultFunctionNames() {
classToFunction.clear();
return this;
}
/**
* Builds an instance of {@link MFFunctionRegistry}.
*
* @return the function registry created.
* @internal ICU 72 technology preview
* @deprecated This API is for technology preview only.
*/
@Deprecated
public MFFunctionRegistry build() {
return new MFFunctionRegistry(this);
}
}
}