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}