001package org.hl7.fhir.utilities.i18n;
002
003import java.text.MessageFormat;
004import java.util.Locale;
005import java.util.Objects;
006import java.util.ResourceBundle;
007
008
009/**
010 * Handles the locale, ResourceBundle and String formatting for i18n
011 * This abstract class should be extended when implementing a IWorkerContext Interface.
012 */
013public abstract class I18nBase {
014
015  private Locale locale;
016  private ResourceBundle i18nMessages;
017  private boolean warnAboutMissingMessages = true;
018
019  public Locale getLocale() {
020    if (Objects.nonNull(locale)) {
021      return locale;
022    } else {
023      return Locale.US;
024    }
025  }
026
027  public void setLocale(Locale locale) {
028    this.locale = locale;
029    setValidationMessageLanguage(getLocale());
030  }
031
032  /**
033   * Verifies if a {@link ResourceBundle} has been loaded for the current {@link Locale}. If not, it triggers a load.
034   */
035  private void checkResourceBundleIsLoaded() {
036    if (i18nMessages == null) {
037      setValidationMessageLanguage(getLocale());
038    }
039  }
040
041  /**
042   * Checks the loaded {@link ResourceBundle} to see if the passed in message exists with the current loaded {@link Locale}.
043   * If no {@link Locale} is currently loaded, it will load the {@link Locale} (default {@link Locale#US} is none is
044   * specified), and search.
045   * @param message The {@link String} message to search for within the current {@link Locale}
046   * @return {@link Boolean#TRUE} if the message exists within the loaded {@link Locale}.
047   */
048  private boolean messageExistsForLocale(String message, boolean hasArgs) {
049    checkResourceBundleIsLoaded();
050    if (!i18nMessages.containsKey(message)) {
051      if (warnAboutMissingMessages && (hasArgs || !message.contains(" "))) {
052        System.out.println("Attempting to localize message " + message + ", but no such equivalent message exists for" +
053            " the local " + getLocale());
054      }
055    }
056    return i18nMessages.containsKey(message);
057  }
058
059  /**
060   * Formats the given message, if needed, with the passed in message arguments.
061   * @param theMessage Base message to format.
062   * @param theMessageArguments Placeholder arguments, if needed.
063   * @return The formatted, internationalized, {@link String}
064   */
065  public String formatMessage(String theMessage, Object... theMessageArguments) {
066    String message = theMessage;
067    if (messageExistsForLocale(theMessage, (theMessageArguments != null && theMessageArguments.length > 0))) {
068      if (Objects.nonNull(theMessageArguments) && theMessageArguments.length > 0) {
069        message = MessageFormat.format(i18nMessages.getString(theMessage), theMessageArguments);
070      } else {
071        message = i18nMessages.getString(theMessage);
072      }
073    }
074    return message;
075  }
076
077  /**
078   * Loads the corresponding {@link ResourceBundle} for the passed in {@link Locale}.
079   * @param locale {@link Locale} to load resources for.
080   */
081  public void setValidationMessageLanguage(Locale locale) {
082    i18nMessages = ResourceBundle.getBundle("Messages", locale);
083  }
084
085  public boolean isWarnAboutMissingMessages() {
086    return warnAboutMissingMessages;
087  }
088
089  public void setWarnAboutMissingMessages(boolean warnAboutMissingMessages) {
090    this.warnAboutMissingMessages = warnAboutMissingMessages;
091  }
092  
093  
094}