001package ca.uhn.fhir.i18n; 002 003import static org.apache.commons.lang3.StringUtils.isNotBlank; 004 005/* 006 * #%L 007 * HAPI FHIR - Core Library 008 * %% 009 * Copyright (C) 2014 - 2017 University Health Network 010 * %% 011 * Licensed under the Apache License, Version 2.0 (the "License"); 012 * you may not use this file except in compliance with the License. 013 * You may obtain a copy of the License at 014 * 015 * http://www.apache.org/licenses/LICENSE-2.0 016 * 017 * Unless required by applicable law or agreed to in writing, software 018 * distributed under the License is distributed on an "AS IS" BASIS, 019 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 020 * See the License for the specific language governing permissions and 021 * limitations under the License. 022 * #L% 023 */ 024 025import java.text.MessageFormat; 026import java.util.ArrayList; 027import java.util.Enumeration; 028import java.util.HashSet; 029import java.util.List; 030import java.util.Map; 031import java.util.ResourceBundle; 032import java.util.Set; 033import java.util.concurrent.ConcurrentHashMap; 034 035import ca.uhn.fhir.context.ConfigurationException; 036 037/** 038 * This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with caution 039 */ 040public class HapiLocalizer { 041 042 private static boolean ourFailOnMissingMessage; 043 private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(HapiLocalizer.class); 044 public static final String UNKNOWN_I18N_KEY_MESSAGE = "!MESSAGE!"; 045 046 private List<ResourceBundle> myBundle = new ArrayList<ResourceBundle>(); 047 private String[] myBundleNames; 048 private final Map<String, MessageFormat> myKeyToMessageFormat = new ConcurrentHashMap<String, MessageFormat>(); 049 050 public HapiLocalizer() { 051 this(HapiLocalizer.class.getPackage().getName() + ".hapi-messages"); 052 } 053 054 public HapiLocalizer(String... theBundleNames) { 055 myBundleNames = theBundleNames; 056 init(); 057 } 058 059 private String findFormatString(String theQualifiedKey) { 060 String formatString = null; 061 for (ResourceBundle nextBundle : myBundle) { 062 if (nextBundle.containsKey(theQualifiedKey)) { 063 formatString = nextBundle.getString(theQualifiedKey); 064 } 065 if (isNotBlank(formatString)) { 066 break; 067 } 068 } 069 070 if (formatString == null) { 071 ourLog.warn("Unknown localization key: {}", theQualifiedKey); 072 if (ourFailOnMissingMessage) { 073 throw new ConfigurationException("Unknown localization key: " + theQualifiedKey); 074 } 075 formatString = UNKNOWN_I18N_KEY_MESSAGE; 076 } 077 return formatString; 078 } 079 080 public Set<String> getAllKeys(){ 081 HashSet<String> retVal = new HashSet<String>(); 082 for (ResourceBundle nextBundle : myBundle) { 083 Enumeration<String> keysEnum = nextBundle.getKeys(); 084 while (keysEnum.hasMoreElements()) { 085 retVal.add(keysEnum.nextElement()); 086 } 087 } 088 return retVal; 089 } 090 091 public String getMessage(Class<?> theType, String theKey, Object... theParameters) { 092 return getMessage(theType.getName() + '.' + theKey, theParameters); 093 } 094 095 public String getMessage(String theQualifiedKey, Object... theParameters) { 096 if (theParameters != null && theParameters.length > 0) { 097 MessageFormat format = myKeyToMessageFormat.get(theQualifiedKey); 098 if (format != null) { 099 return format.format(theParameters).toString(); 100 } 101 102 String formatString = findFormatString(theQualifiedKey); 103 104 format = new MessageFormat(formatString.trim()); 105 myKeyToMessageFormat.put(theQualifiedKey, format); 106 return format.format(theParameters).toString(); 107 } 108 String retVal = findFormatString(theQualifiedKey); 109 return retVal; 110 } 111 112 protected void init() { 113 for (String nextName : myBundleNames) { 114 myBundle.add(ResourceBundle.getBundle(nextName)); 115 } 116 } 117 118 /** 119 * This <b>global setting</b> causes the localizer to fail if any attempts 120 * are made to retrieve a key that does not exist. This method is primarily for 121 * unit tests. 122 */ 123 public static void setOurFailOnMissingMessage(boolean ourFailOnMissingMessage) { 124 HapiLocalizer.ourFailOnMissingMessage = ourFailOnMissingMessage; 125 } 126 127}