View Javadoc

1   /*
2    * Copyright (c) 2009 QOS.ch All rights reserved.
3    * 
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   * 
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   * 
14   * THE SOFTWARE IS PROVIDED "AS  IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package ch.qos.cal10n.verifier;
24  
25  import java.util.ArrayList;
26  import java.util.Enumeration;
27  import java.util.HashSet;
28  import java.util.List;
29  import java.util.Locale;
30  import java.util.ResourceBundle;
31  import java.util.Set;
32  
33  import ch.qos.cal10n.util.AnnotationExtractor;
34  import ch.qos.cal10n.util.PropertyResourceBundleFinder;
35  import ch.qos.cal10n.util.StringToLocale;
36  import ch.qos.cal10n.verifier.Cal10nError.ErrorType;
37  
38  /**
39   * Given an enum class, verify that the resource bundles corresponding to a
40   * given locale contains the correct keys.
41   * 
42   * @author Ceki Gulcu
43   */
44  public class MessageKeyVerifier implements IMessageKeyVerifier {
45  
46    Class<? extends Enum<?>> enumType;
47    String enumTypeAsStr;
48  
49    public MessageKeyVerifier(Class<? extends Enum<?>> enumClass) {
50      this.enumType = enumClass;
51      this.enumTypeAsStr = enumClass.getName();
52    }
53  
54    @SuppressWarnings("unchecked")
55    public MessageKeyVerifier(String enumTypeAsStr) {
56      this.enumTypeAsStr = enumTypeAsStr;
57      String errMsg = "Failed to find enum class [" + enumTypeAsStr + "]";
58      try {
59        this.enumType = (Class<? extends Enum<?>>) Class.forName(enumTypeAsStr);
60      } catch (ClassNotFoundException e) {
61        throw new IllegalStateException(errMsg, e);
62      } catch (NoClassDefFoundError e) {
63        throw new IllegalStateException(errMsg, e);
64      }
65    }
66  
67    public Class<? extends Enum<?>> getEnumType() {
68      return enumType;
69    }
70  
71    public String getEnumTypeAsStr() {
72      return enumTypeAsStr;
73    }
74  
75    public List<Cal10nError> verify(Locale locale) {
76      List<Cal10nError> errorList = new ArrayList<Cal10nError>();
77  
78      String baseName = AnnotationExtractor.getBaseName(enumType);
79  
80      if (baseName == null) {
81        errorList.add(new Cal10nError(ErrorType.MISSING_BN_ANNOTATION, "",
82            enumType, locale, ""));
83        // no point in continuing
84        return errorList;
85      }
86  
87      ResourceBundle rb = PropertyResourceBundleFinder.getBundle(this.getClass()
88          .getClassLoader(), baseName, locale);
89  
90      ErrorFactory errorFactory = new ErrorFactory(enumType, locale, baseName);
91  
92      if (rb == null) {
93        errorList.add(errorFactory.buildError(ErrorType.FAILED_TO_FIND_RB, ""));
94     // no point in continuing
95        return errorList;
96      }
97      
98      Set<String> rbKeySet = buildKeySetFromEnumeration(rb.getKeys());
99  
100     if (rbKeySet.size() == 0) {
101       errorList.add(errorFactory.buildError(ErrorType.EMPTY_RB, ""));
102     }
103 
104     Enum<?>[] enumArray = enumType.getEnumConstants();
105     if (enumArray == null || enumArray.length == 0) {
106       errorList.add(errorFactory.buildError(ErrorType.EMPTY_ENUM, ""));
107     }
108 
109     if (errorList.size() != 0) {
110       return errorList;
111     }
112 
113     for (Enum<?> e : enumArray) {
114       String enumKey = e.toString();
115       if (rbKeySet.contains(enumKey)) {
116         rbKeySet.remove(enumKey);
117       } else {
118         errorList.add(errorFactory.buildError(ErrorType.ABSENT_IN_RB, enumKey));
119       }
120     }
121 
122     for (String rbKey : rbKeySet) {
123       errorList.add(errorFactory.buildError(ErrorType.ABSENT_IN_ENUM, rbKey));
124     }
125     return errorList;
126   }
127 
128   private Set<String> buildKeySetFromEnumeration(Enumeration<String> e) {
129     Set<String> set = new HashSet<String>();
130     while (e.hasMoreElements()) {
131       String s = e.nextElement();
132       set.add(s);
133     }
134     return set;
135   }
136 
137   public List<String> typeIsolatedVerify(Locale locale) {
138     List<Cal10nError> errorList = verify(locale);
139     List<String> strList = new ArrayList<String>();
140     for (Cal10nError error : errorList) {
141       strList.add(error.toString());
142     }
143     return strList;
144   }
145 
146   /***
147    * Verify all declared locales in one step.
148    */
149   public List<Cal10nError> verifyAllLocales() {
150     List<Cal10nError> errorList = new ArrayList<Cal10nError>();
151 
152     String[] localeNameArray = getLocaleNames();
153 
154     if (localeNameArray == null || localeNameArray.length == 0) {
155       String errMsg = "Missing @LocaleNames annotation in enum type ["
156           + enumTypeAsStr + "]";
157       throw new IllegalStateException(errMsg);
158     }
159     for (String localeName : localeNameArray) {
160       Locale locale = StringToLocale.toLocale(localeName);
161       System.out.println(locale);
162       List<Cal10nError> tmpList = verify(locale);
163       errorList.addAll(tmpList);
164     }
165 
166     return errorList;
167   }
168 
169   public String[] getLocaleNames() {
170     String[] localeNameArray = AnnotationExtractor.getLocaleNames(enumType);
171     return localeNameArray;
172   }
173 
174   public String getBaseName() {
175     String rbName = AnnotationExtractor.getBaseName(enumType);
176     return rbName;
177   }
178 
179 }