All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.omnifaces.utils.text.SubFormatter Maven / Gradle / Ivy

There is a newer version: 0.14
Show newest version
/*
 * Copyright 2021 OmniFaces
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package org.omnifaces.utils.text;

import static java.text.NumberFormat.getCurrencyInstance;
import static java.text.NumberFormat.getIntegerInstance;
import static java.text.NumberFormat.getPercentInstance;
import static java.time.format.DateTimeFormatter.ofLocalizedDate;
import static java.time.format.DateTimeFormatter.ofLocalizedDateTime;
import static java.time.format.DateTimeFormatter.ofLocalizedTime;
import static java.time.format.DateTimeFormatter.ofPattern;
import static java.time.format.FormatStyle.FULL;
import static java.time.format.FormatStyle.LONG;
import static java.time.format.FormatStyle.MEDIUM;
import static java.time.format.FormatStyle.SHORT;
import static org.omnifaces.utils.Lang.isEmpty;
import static org.omnifaces.utils.text.FormatterUtil.firstIndexOfNonQuoted;
import static org.omnifaces.utils.text.FormatterUtil.getNumber;
import static org.omnifaces.utils.text.FormatterUtil.getTemporalAccessor;

import java.io.Serializable;
import java.text.ChoiceFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.Map;
import java.util.function.Function;

@FunctionalInterface
public interface SubFormatter extends Serializable {

	/**
	 * Formats the the parameter with the given name from the given set of parameters.
	 *
	 * {@link SubFormatter}s can recursively format messages using the supplied parameters and the given {@link NameBasedMessageFormat} factory. The
	 * {@link NameBasedMessageFormat} factory should create an instance that uses the same settings as the format that is calling the current
	 * sub-formatter, but with a different pattern.
	 *
	 * @param name
	 *            the name of the parameter to format
	 * @param parameters
	 *            the map that contains all the parameters used in the current formatter operation
	 * @param nameBasedMessageFormatFactory
	 *            a factory to create a new {@link NameBasedMessageFormat} for any recursively defined message patterns.
	 * @return the formatted parameter
	 */
	String format(String name, Map parameters, Function nameBasedMessageFormatFactory);

	static SubFormatter stringFormatter(String modifier, Locale locale) {
		return (name, parameters, patternFormatFactory) -> "" + parameters.get(name);
	}

	static SubFormatter numberFormatter(String modifier, Locale locale) {
		if (isEmpty(modifier)) {
			return (name, parameters, patternFormatFactory) -> NumberFormat.getInstance(locale).format(getNumber(parameters.get(name)));
		}

		switch (modifier) {
			case "integer":
				return (name, parameters, patternFormatFactory) -> getIntegerInstance(locale).format(getNumber(parameters.get(name)));
			case "currency":
				return (name, parameters, patternFormatFactory) -> getCurrencyInstance(locale).format(getNumber(parameters.get(name)));
			case "percent":
				return (name, parameters, patternFormatFactory) -> getPercentInstance(locale).format(getNumber(parameters.get(name)));
			default:
				return (name, parameters, patternFormatFactory) -> new DecimalFormat(modifier, DecimalFormatSymbols.getInstance(locale)).format(getNumber(parameters
						.get(name)));
		}
	}

	static SubFormatter dateFormatter(String modifier, Locale locale) {
		DateTimeFormatter dateTimeFormatter;
		if (isEmpty(modifier)) {
			dateTimeFormatter = ofLocalizedDate(MEDIUM).withLocale(locale);
		}
		else {
			switch (modifier) {
				case "short":
					dateTimeFormatter = ofLocalizedDate(SHORT).withLocale(locale);
					break;
				case "medium":
					dateTimeFormatter = ofLocalizedDate(MEDIUM).withLocale(locale);
					break;
				case "long":
					dateTimeFormatter = ofLocalizedDate(LONG).withLocale(locale);
					break;
				case "full":
					dateTimeFormatter = ofLocalizedDate(FULL).withLocale(locale);
					break;
				default:
					dateTimeFormatter = ofPattern(modifier).withLocale(locale);
			}
		}

		return (name, parameters, patternFormatFactory) -> dateTimeFormatter.format(getTemporalAccessor(parameters.get(name)));
	}

	static SubFormatter dateTimeFormatter(String modifier, Locale locale) {
		DateTimeFormatter dateTimeFormatter;
		if (isEmpty(modifier)) {
			dateTimeFormatter = ofLocalizedDateTime(MEDIUM).withLocale(locale);
		}
		else {
			switch (modifier) {
				case "short":
					dateTimeFormatter = ofLocalizedDateTime(SHORT).withLocale(locale);
					break;
				case "medium":
					dateTimeFormatter = ofLocalizedDateTime(MEDIUM).withLocale(locale);
					break;
				case "long":
					dateTimeFormatter = ofLocalizedDateTime(LONG).withLocale(locale);
					break;
				case "full":
					dateTimeFormatter = ofLocalizedDateTime(FULL).withLocale(locale);
					break;
				default:
					dateTimeFormatter = ofPattern(modifier).withLocale(locale);
			}
		}

		return (name, parameters, patternFormatFactory) -> dateTimeFormatter.format(getTemporalAccessor(parameters.get(name)));
	}

	static SubFormatter timeFormatter(String modifier, Locale locale) {
		DateTimeFormatter dateTimeFormatter;
		if (isEmpty(modifier)) {
			dateTimeFormatter = ofLocalizedTime(MEDIUM).withLocale(locale);
		}
		else {
			switch (modifier) {
				case "short":
					dateTimeFormatter = ofLocalizedTime(SHORT).withLocale(locale);
					break;
				case "medium":
					dateTimeFormatter = ofLocalizedTime(MEDIUM).withLocale(locale);
					break;
				case "long":
					dateTimeFormatter = ofLocalizedTime(LONG).withLocale(locale);
					break;
				case "full":
					dateTimeFormatter = ofLocalizedTime(FULL).withLocale(locale);
					break;
				default:
					dateTimeFormatter = ofPattern(modifier).withLocale(locale);
			}
		}

		return (name, parameters, patternFormatFactory) -> dateTimeFormatter.format(getTemporalAccessor(parameters.get(name)));
	}

	static SubFormatter choiceFormatter(String modifier, Locale locale) {
		return (name, parameters, patternFormatFactory) -> {
			Number number = getNumber(parameters.get(name));

			ChoiceFormat choiceFormat = new ChoiceFormat(modifier);
			String format = choiceFormat.format(number.doubleValue());

			if (format.indexOf('{') >= 0) {
				return patternFormatFactory.apply(format).format(parameters);
			}

			return format;
		};
	}

	static SubFormatter optionalFormatter(String modifier, Locale locale) {
		String replacementPattern;
		String formatPattern;

		int indexOfSeparator = firstIndexOfNonQuoted(modifier, '|');
		if (indexOfSeparator >= 0) {
			replacementPattern = modifier.substring(0, indexOfSeparator);
			formatPattern = modifier.substring(indexOfSeparator + 1);
		} else {
			replacementPattern = modifier;
			formatPattern = null;
		}

		return (name, parameters, patternFormatFactory) -> {
			Object parameter = parameters.get(name);

			String outputPattern;

			if (parameter == null) {
				outputPattern = replacementPattern;
			} else if (formatPattern == null) {
				return "" + parameter;
			} else {
				outputPattern = formatPattern;
			}

			if (outputPattern.contains("{") || outputPattern.contains("'")) {
				// Pattern contains special characters, format using a new NameBasedMessageFormat instance
				return patternFormatFactory.apply(outputPattern)
										   .format(parameters);
			}

			return outputPattern;
		};
	}

	static SubFormatter booleanFormatter(String modifier, Locale locale) {
		String truePattern;
		String falsePattern;

		int indexOfSeparator = firstIndexOfNonQuoted(modifier, '|');

		if (indexOfSeparator >= 0) {
			truePattern = modifier.substring(0, indexOfSeparator);
			falsePattern = modifier.substring(indexOfSeparator + 1);
		} else {
			truePattern = modifier;
			falsePattern = "";
		}

		return (name, parameters, patternFormatFactory) -> {
			if (Boolean.parseBoolean("" + parameters.get(name))) {
				return patternFormatFactory.apply(truePattern)
				                           .format(parameters);
			}
			else {
				return patternFormatFactory.apply(falsePattern)
				                           .format(parameters);
			}
		};
	}

	/**
	 * Formatter that always formats the given modifier as a pattern instead of using the given parameter. This formatter may be useful for testing or
	 * for more complex dynamic formatting.
	 *
	 * @param modifier the {@link String} to use as alternative
	 * @param locale the locale to use when formatting
	 * @return a formatter that outputs the given modifier, formatted as pattern
	 */
	static SubFormatter alternativeFormatter(String modifier, Locale locale) {
		return (name, parameters, patternFormatFactory) -> patternFormatFactory.apply(modifier).format(parameters);
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy