001 /*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2014 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * SonarQube is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
019 */
020 package org.sonar.api.utils;
021
022 import com.google.common.collect.Iterators;
023 import com.google.common.collect.Lists;
024 import org.slf4j.Logger;
025 import org.slf4j.LoggerFactory;
026
027 import java.util.*;
028
029 public class LocalizedMessages extends ResourceBundle {
030
031 private static final Logger LOG = LoggerFactory.getLogger(LocalizedMessages.class);
032
033 private Locale locale;
034 private List<ResourceBundle> bundles;
035
036 /**
037 * Constructs a resource bundle from a list of other resource bundles. If
038 * there are duplicate keys, the key from the resource bundle with the
039 * smallest index takes precedence.
040 */
041 public LocalizedMessages(Locale locale, String... basenames) {
042 this.locale = locale;
043 bundles = new ArrayList<ResourceBundle>(basenames.length);
044 for (String basename : basenames) {
045 bundles.add(getBundle("sonar.bundles." + basename, locale));
046 }
047 }
048
049 @Override
050 public Locale getLocale() {
051 return locale;
052 }
053
054 public String format(String key, Object... args) {
055 return format(true, key, args);
056 }
057
058 public String formatQuietly(String key, Object... args) {
059 return format(false, key, args);
060 }
061
062 private String format(boolean logIfMissing, String key, Object... args) {
063 try {
064 String message = getString(key);
065 return String.format(locale, message, args);
066
067 } catch (MissingResourceException e) {
068 if (logIfMissing) {
069 LOG.warn("Missing translation: key==" + key + ",locale=" + locale);
070 }
071 return key;
072 }
073 }
074
075 /*
076 * (non-Javadoc)
077 *
078 * @see java.util.ResourceBundle#getKeys()
079 */
080 @Override
081 public Enumeration<String> getKeys() {
082 return new KeyEnumeration();
083 }
084
085 /*
086 * (non-Javadoc)
087 *
088 * @see java.util.ResourceBundle#handleGetObject(java.lang.String)
089 */
090 @Override
091 protected Object handleGetObject(String key) {
092 for (ResourceBundle b : bundles) {
093 try {
094 return b.getObject(key);
095 } catch (MissingResourceException mre) {
096 // iterate
097 }
098 }
099 throw new MissingResourceException(null, null, key);
100 }
101
102 private class KeyEnumeration implements Enumeration<String> {
103 private Set<String> keys = new HashSet<String>();
104
105 // Set iterator to simulate enumeration
106 private Iterator<String> i;
107
108 // Constructor
109 {
110 for (ResourceBundle b : bundles) {
111 keys.addAll(Lists.newArrayList(Iterators.forEnumeration(b.getKeys())));
112 }
113 i = keys.iterator();
114 }
115
116 public boolean hasMoreElements() {
117 return i.hasNext();
118 }
119
120 public String nextElement() {
121 return i.next();
122 }
123 }
124 }