View Javadoc
1   package ca.uhn.fhir.i18n;
2   
3   import ca.uhn.fhir.context.ConfigurationException;
4   
5   import java.text.MessageFormat;
6   import java.util.*;
7   import java.util.concurrent.ConcurrentHashMap;
8   
9   import static org.apache.commons.lang3.StringUtils.isNotBlank;
10  import static org.apache.commons.lang3.StringUtils.trim;
11  
12  /*
13   * #%L
14   * HAPI FHIR - Core Library
15   * %%
16   * Copyright (C) 2014 - 2018 University Health Network
17   * %%
18   * Licensed under the Apache License, Version 2.0 (the "License");
19   * you may not use this file except in compliance with the License.
20   * You may obtain a copy of the License at
21   * 
22   * http://www.apache.org/licenses/LICENSE-2.0
23   * 
24   * Unless required by applicable law or agreed to in writing, software
25   * distributed under the License is distributed on an "AS IS" BASIS,
26   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27   * See the License for the specific language governing permissions and
28   * limitations under the License.
29   * #L%
30   */
31  
32  /**
33   * This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with caution
34   */
35  public class HapiLocalizer {
36  
37  	@SuppressWarnings("WeakerAccess")
38  	public static final String UNKNOWN_I18N_KEY_MESSAGE = "!MESSAGE!";
39  	private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(HapiLocalizer.class);
40  	private static boolean ourFailOnMissingMessage;
41  	private final Map<String, MessageFormat> myKeyToMessageFormat = new ConcurrentHashMap<>();
42  	private List<ResourceBundle> myBundle = new ArrayList<>();
43  	private String[] myBundleNames;
44  
45  	public HapiLocalizer() {
46  		this(HapiLocalizer.class.getPackage().getName() + ".hapi-messages");
47  	}
48  
49  	public HapiLocalizer(String... theBundleNames) {
50  		myBundleNames = theBundleNames;
51  		init();
52  	}
53  
54  	public Set<String> getAllKeys() {
55  		HashSet<String> retVal = new HashSet<>();
56  		for (ResourceBundle nextBundle : myBundle) {
57  			Enumeration<String> keysEnum = nextBundle.getKeys();
58  			while (keysEnum.hasMoreElements()) {
59  				retVal.add(keysEnum.nextElement());
60  			}
61  		}
62  		return retVal;
63  	}
64  
65  	/**
66  	 * @return Returns the raw message format string for the given key, or returns {@link #UNKNOWN_I18N_KEY_MESSAGE} if not found
67  	 */
68  	@SuppressWarnings("WeakerAccess")
69  	public String getFormatString(String theQualifiedKey) {
70  		String formatString = null;
71  		for (ResourceBundle nextBundle : myBundle) {
72  			if (nextBundle.containsKey(theQualifiedKey)) {
73  				formatString = nextBundle.getString(theQualifiedKey);
74  				formatString = trim(formatString);
75  			}
76  			if (isNotBlank(formatString)) {
77  				break;
78  			}
79  		}
80  
81  		if (formatString == null) {
82  			ourLog.warn("Unknown localization key: {}", theQualifiedKey);
83  			if (ourFailOnMissingMessage) {
84  				throw new ConfigurationException("Unknown localization key: " + theQualifiedKey);
85  			}
86  			formatString = UNKNOWN_I18N_KEY_MESSAGE;
87  		}
88  		return formatString;
89  	}
90  
91  	public String getMessage(Class<?> theType, String theKey, Object... theParameters) {
92  		return getMessage(toKey(theType, theKey), theParameters);
93  	}
94  
95  	public String getMessage(String theQualifiedKey, Object... theParameters) {
96  		if (theParameters != null && theParameters.length > 0) {
97  			MessageFormat format = myKeyToMessageFormat.get(theQualifiedKey);
98  			if (format != null) {
99  				return format.format(theParameters);
100 			}
101 
102 			String formatString = getFormatString(theQualifiedKey);
103 
104 			format = new MessageFormat(formatString.trim());
105 			myKeyToMessageFormat.put(theQualifiedKey, format);
106 			return format.format(theParameters);
107 		}
108 		return getFormatString(theQualifiedKey);
109 	}
110 
111 	protected void init() {
112 		for (String nextName : myBundleNames) {
113 			myBundle.add(ResourceBundle.getBundle(nextName));
114 		}
115 	}
116 
117 	/**
118 	 * This <b>global setting</b> causes the localizer to fail if any attempts
119 	 * are made to retrieve a key that does not exist. This method is primarily for
120 	 * unit tests.
121 	 */
122 	public static void setOurFailOnMissingMessage(boolean ourFailOnMissingMessage) {
123 		HapiLocalizer.ourFailOnMissingMessage = ourFailOnMissingMessage;
124 	}
125 
126 	public static String toKey(Class<?> theType, String theKey) {
127 		return theType.getName() + '.' + theKey;
128 	}
129 
130 }