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     */
020    package org.sonar.core.i18n;
021    
022    import com.google.common.collect.Lists;
023    import org.apache.commons.lang.StringUtils;
024    import org.sonar.api.ServerComponent;
025    
026    import java.util.List;
027    import java.util.Locale;
028    
029    public 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    }