001/*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar 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 * Sonar 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
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019 */
020package org.sonar.api.utils;
021
022import com.google.common.collect.Iterators;
023import com.google.common.collect.Lists;
024import org.slf4j.Logger;
025import org.slf4j.LoggerFactory;
026
027import java.util.*;
028
029public 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
081  @Override
082  public Enumeration<String> getKeys() {
083    return new Enumeration<String>() {
084      private Set<String> keys = new HashSet<String>();
085
086      // Set iterator to simulate enumeration
087      private Iterator<String> i;
088
089      // Constructor
090      {
091        for (ResourceBundle b : bundles) {
092          keys.addAll(Lists.newArrayList(Iterators.forEnumeration(b.getKeys())));
093        }
094        i = keys.iterator();
095      }
096
097      public boolean hasMoreElements() {
098        return i.hasNext();
099      }
100
101      public String nextElement() {
102        return i.next();
103      }
104    };
105  }
106
107  /*
108    * (non-Javadoc)
109    *
110    * @see java.util.ResourceBundle#handleGetObject(java.lang.String)
111    */
112
113  @Override
114  protected Object handleGetObject(String key) {
115    for (ResourceBundle b : bundles) {
116      try {
117        return b.getObject(key);
118      } catch (MissingResourceException mre) {
119        // iterate 
120      }
121    }
122    throw new MissingResourceException(null, null, key);
123  }
124}