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.core.i18n;
021
022import com.google.common.collect.Lists;
023import org.apache.commons.lang.StringUtils;
024import org.sonar.api.ServerComponent;
025
026import java.util.List;
027import java.util.Locale;
028
029public class RuleI18nManager implements ServerComponent {
030
031  private static final String NAME_SUFFIX = ".name";
032  private static final String RULE_PREFIX = "rule.";
033
034  private I18nManager i18nManager;
035  private RuleKey[] ruleKeys;
036
037  public RuleI18nManager(I18nManager i18nManager) {
038    this.i18nManager = i18nManager;
039  }
040
041  public void start() {
042    List<RuleKey> list = Lists.newArrayList();
043    for (String propertyKey : i18nManager.getPropertyKeys()) {
044      if (isRuleProperty(propertyKey)) {
045        list.add(extractRuleKey(propertyKey));
046      }
047    }
048    this.ruleKeys = list.toArray(new RuleKey[list.size()]);
049  }
050
051  public String getName(String repositoryKey, String ruleKey, Locale locale) {
052    return message(repositoryKey, ruleKey, locale, NAME_SUFFIX);
053  }
054
055  public String getDescription(String repositoryKey, String ruleKey, Locale locale) {
056    String relatedProperty = new StringBuilder().append(RULE_PREFIX).append(repositoryKey).append(".").append(ruleKey).append(NAME_SUFFIX).toString();
057
058    Locale localeWithoutCountry = (locale.getCountry() == null ? locale : new Locale(locale.getLanguage()));
059    String ruleDescriptionFilePath = "rules/" + repositoryKey + "/" + ruleKey + ".html";
060    String description = i18nManager.messageFromFile(localeWithoutCountry, ruleDescriptionFilePath, relatedProperty, true);
061    if (description == null) {
062      // Following line is to ensure backward compatibility (SONAR-3319)
063      description = lookUpDescriptionInFormerLocation(ruleKey, relatedProperty, localeWithoutCountry);
064      if (description == null && !"en".equals(localeWithoutCountry.getLanguage())) {
065        // nothing was found, let's get the value of the default bundle
066        description = i18nManager.messageFromFile(Locale.ENGLISH, ruleDescriptionFilePath, relatedProperty, true);
067      }
068    }
069    return description;
070  }
071
072  /*
073   * Method used to ensure backward compatibility for language plugins that store HTML rule description files in the former
074   * location (which was used prior to Sonar 3.0).
075   * 
076   * See http://jira.codehaus.org/browse/SONAR-3319
077   */
078  private String lookUpDescriptionInFormerLocation(String ruleKey, String relatedProperty, Locale localeWithoutCountry) {
079    String description = i18nManager.messageFromFile(localeWithoutCountry, ruleKey + ".html", relatedProperty, true);
080    if (description == null && !"en".equals(localeWithoutCountry.getLanguage())) {
081      // nothing was found, let's get the value of the default bundle
082      description = i18nManager.messageFromFile(Locale.ENGLISH, ruleKey + ".html", relatedProperty, true);
083    }
084    return description;
085  }
086
087  public String getParamDescription(String repositoryKey, String ruleKey, String paramKey, Locale locale) {
088    return message(repositoryKey, ruleKey, locale, ".param." + paramKey);
089  }
090
091  String message(String repositoryKey, String ruleKey, Locale locale, String suffix) {
092    String propertyKey = new StringBuilder().append(RULE_PREFIX).append(repositoryKey).append(".").append(ruleKey).append(suffix).toString();
093    return i18nManager.message(locale, propertyKey, null);
094  }
095
096  public List<RuleKey> searchNames(String search, Locale locale) {
097    List<RuleKey> result = Lists.newArrayList();
098    for (RuleKey ruleKey : ruleKeys) {
099      String name = i18nManager.message(locale, ruleKey.getNameProperty(), null);
100      if (name != null && StringUtils.indexOfIgnoreCase(name, search) >= 0) {
101        result.add(ruleKey);
102      }
103    }
104    return result;
105  }
106
107  RuleKey[] getRuleKeys() {
108    return ruleKeys;
109  }
110
111  static RuleKey extractRuleKey(String propertyKey) {
112    String s = StringUtils.substringBetween(propertyKey, RULE_PREFIX, NAME_SUFFIX);
113    String ruleKey = StringUtils.substringAfter(s, ".");
114    String repository = StringUtils.substringBefore(s, ".");
115    return new RuleKey(repository, ruleKey);
116  }
117
118  static boolean isRuleProperty(String propertyKey) {
119    return StringUtils.startsWith(propertyKey, RULE_PREFIX) && StringUtils.endsWith(propertyKey, NAME_SUFFIX) && !propertyKey.contains(".param.");
120  }
121
122  public static class RuleKey {
123    private String repositoryKey;
124    private String key;
125
126    RuleKey(String repositoryKey, String key) {
127      this.repositoryKey = repositoryKey;
128      this.key = key;
129    }
130
131    public String getRepositoryKey() {
132      return repositoryKey;
133    }
134
135    public String getKey() {
136      return key;
137    }
138
139    public String getNameProperty() {
140      return new StringBuilder().append(RULE_PREFIX).append(repositoryKey).append(".").append(key).append(NAME_SUFFIX).toString();
141    }
142
143    @Override
144    public boolean equals(Object o) {
145      if (this == o) {
146        return true;
147      }
148      if (o == null || getClass() != o.getClass()) {
149        return false;
150      }
151      RuleKey ruleKey = (RuleKey) o;
152      if (!key.equals(ruleKey.key)) {
153        return false;
154      }
155      if (!repositoryKey.equals(ruleKey.repositoryKey)) {
156        return false;
157      }
158      return true;
159    }
160
161    @Override
162    public int hashCode() {
163      int result = repositoryKey.hashCode();
164      result = 31 * result + key.hashCode();
165      return result;
166    }
167
168    @Override
169    public String toString() {
170      return new StringBuilder().append(repositoryKey).append(":").append(key).toString();
171    }
172  }
173}