KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > puppycrawl > tools > checkstyle > checks > TranslationCheck


1 ////////////////////////////////////////////////////////////////////////////////
2
// checkstyle: Checks Java source code for adherence to a set of rules.
3
// Copyright (C) 2001-2005 Oliver Burn
4
//
5
// This library is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU Lesser General Public
7
// License as published by the Free Software Foundation; either
8
// version 2.1 of the License, or (at your option) any later version.
9
//
10
// This library is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
// Lesser General Public License for more details.
14
//
15
// You should have received a copy of the GNU Lesser General Public
16
// License along with this library; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
////////////////////////////////////////////////////////////////////////////////
19
package com.puppycrawl.tools.checkstyle.checks;
20
21 import java.io.File JavaDoc;
22 import java.io.FileInputStream JavaDoc;
23 import java.io.FileNotFoundException JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.util.Enumeration JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.HashSet JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Properties JavaDoc;
32 import java.util.Set JavaDoc;
33
34 import com.puppycrawl.tools.checkstyle.Defn;
35 import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
36 import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
37 import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
38 import com.puppycrawl.tools.checkstyle.api.Utils;
39
40 /**
41  * <p>
42  * The TranslationCheck class helps to ensure the correct translation of code by
43  * checking property files for consistency regarding their keys.
44  * Two property files describing one and the same context are consistent if they
45  * contain the same keys.
46  * </p>
47  * <p>
48  * An example of how to configure the check is:
49  * </p>
50  * <pre>
51  * &lt;module name="Translation"/&gt;
52  * </pre>
53  * @author Alexandra Bunge
54  * @author lkuehne
55  */

56 public class TranslationCheck
57     extends AbstractFileSetCheck
58 {
59     /**
60      * Creates a new <code>TranslationCheck</code> instance.
61      */

62     public TranslationCheck()
63     {
64         setFileExtensions(new String JavaDoc[]{"properties"});
65     }
66
67     /**
68      * Gets the basename (the unique prefix) of a property file. For example
69      * "xyz/messages" is the basename of "xyz/messages.properties",
70      * "xyz/messages_de_AT.properties", "xyz/messages_en.properties", etc.
71      *
72      * @param aFile the file
73      * @return the extracted basename
74      */

75     private static String JavaDoc extractPropertyIdentifier(final File JavaDoc aFile)
76     {
77         final String JavaDoc filePath = aFile.getPath();
78         final int dirNameEnd = filePath.lastIndexOf(File.separatorChar);
79         final int baseNameStart = dirNameEnd + 1;
80         final int underscoreIdx = filePath.indexOf('_', baseNameStart);
81         final int dotIdx = filePath.indexOf('.', baseNameStart);
82         final int cutoffIdx = (underscoreIdx != -1) ? underscoreIdx : dotIdx;
83         return filePath.substring(0, cutoffIdx);
84     }
85
86     /**
87      * Arranges a set of property files by their prefix.
88      * The method returns a Map object. The filename prefixes
89      * work as keys each mapped to a set of files.
90      * @param aPropFiles the set of property files
91      * @return a Map object which holds the arranged property file sets
92      */

93     private static Map JavaDoc arrangePropertyFiles(File JavaDoc[] aPropFiles)
94     {
95         final Map JavaDoc propFileMap = new HashMap JavaDoc();
96
97         for (int i = 0; i < aPropFiles.length; i++) {
98             final File JavaDoc f = aPropFiles[i];
99             final String JavaDoc identifier = extractPropertyIdentifier(f);
100
101             Set JavaDoc fileSet = (Set JavaDoc) propFileMap.get(identifier);
102             if (fileSet == null) {
103                 fileSet = new HashSet JavaDoc();
104                 propFileMap.put(identifier, fileSet);
105             }
106             fileSet.add(f);
107         }
108         return propFileMap;
109     }
110
111
112     /**
113      * Loads the keys of the specified property file into a set.
114      * @param aFile the property file
115      * @return a Set object which holds the loaded keys
116      */

117     private Set JavaDoc loadKeys(File JavaDoc aFile)
118     {
119         final Set JavaDoc keys = new HashSet JavaDoc();
120         InputStream JavaDoc inStream = null;
121
122         try {
123             // Load file and properties.
124
inStream = new FileInputStream JavaDoc(aFile);
125             final Properties JavaDoc props = new Properties JavaDoc();
126             props.load(inStream);
127
128             // Gather the keys and put them into a set
129
final Enumeration JavaDoc e = props.propertyNames();
130             while (e.hasMoreElements()) {
131                 keys.add(e.nextElement());
132             }
133         }
134         catch (final IOException JavaDoc e) {
135             logIOException(e, aFile);
136         }
137         finally {
138             try {
139                 if (inStream != null) {
140                     inStream.close();
141                 }
142             }
143             catch (final IOException JavaDoc e) {
144                 logIOException(e, aFile);
145             }
146         }
147         return keys;
148     }
149
150     /**
151      * helper method to log an io exception.
152      * @param aEx the exception that occured
153      * @param aFile the file that could not be processed
154      */

155     private void logIOException(IOException JavaDoc aEx, File JavaDoc aFile)
156     {
157         String JavaDoc[] args = null;
158         String JavaDoc key = "general.fileNotFound";
159         if (!(aEx instanceof FileNotFoundException JavaDoc)) {
160             args = new String JavaDoc[] {aEx.getMessage()};
161             key = "general.exception";
162         }
163         final LocalizedMessage message =
164             new LocalizedMessage(
165                 0,
166                 Defn.CHECKSTYLE_BUNDLE,
167                 key,
168                 args,
169                 getId(),
170                 this.getClass());
171         final LocalizedMessage[] messages = new LocalizedMessage[] {message};
172         getMessageDispatcher().fireErrors(aFile.getPath(), messages);
173         Utils.getExceptionLogger().debug("IOException occured.", aEx);
174     }
175
176
177     /**
178      * Compares the key sets of the given property files (arranged in a map)
179      * with the specified key set. All missing keys are reported.
180      * @param aKeys the set of keys to compare with
181      * @param aFileMap a Map from property files to their key sets
182      */

183     private void compareKeySets(Set JavaDoc aKeys, Map JavaDoc aFileMap)
184     {
185         final Set JavaDoc fls = aFileMap.entrySet();
186
187         for (final Iterator JavaDoc iter = fls.iterator(); iter.hasNext();) {
188             final Map.Entry JavaDoc entry = (Map.Entry JavaDoc) iter.next();
189             final File JavaDoc currentFile = (File JavaDoc) entry.getKey();
190             final MessageDispatcher dispatcher = getMessageDispatcher();
191             final String JavaDoc path = currentFile.getPath();
192             dispatcher.fireFileStarted(path);
193             final Set JavaDoc currentKeys = (Set JavaDoc) entry.getValue();
194
195             // Clone the keys so that they are not lost
196
final Set JavaDoc keysClone = new HashSet JavaDoc(aKeys);
197             keysClone.removeAll(currentKeys);
198
199             // Remaining elements in the key set are missing in the current file
200
if (!keysClone.isEmpty()) {
201                 for (final Iterator JavaDoc it = keysClone.iterator(); it.hasNext();) {
202                     final Object JavaDoc key = it.next();
203                     log(0, "translation.missingKey", key);
204                 }
205             }
206             fireErrors(path);
207             dispatcher.fireFileFinished(path);
208         }
209     }
210
211
212     /**
213      * Tests whether the given property files (arranged by their prefixes
214      * in a Map) contain the proper keys.
215      *
216      * Each group of files must have the same keys. If this is not the case
217      * an error message is posted giving information which key misses in
218      * which file.
219      *
220      * @param aPropFiles the property files organized as Map
221      */

222     private void checkPropertyFileSets(Map JavaDoc aPropFiles)
223     {
224         final Set JavaDoc entrySet = aPropFiles.entrySet();
225
226         for (final Iterator JavaDoc iterator = entrySet.iterator(); iterator.hasNext();)
227         {
228             final Map.Entry JavaDoc entry = (Map.Entry JavaDoc) iterator.next();
229             final Set JavaDoc files = (Set JavaDoc) entry.getValue();
230
231             if (files.size() >= 2) {
232                 // build a map from files to the keys they contain
233
final Set JavaDoc keys = new HashSet JavaDoc();
234                 final Map JavaDoc fileMap = new HashMap JavaDoc();
235
236                 for (final Iterator JavaDoc iter = files.iterator(); iter.hasNext();) {
237                     final File JavaDoc file = (File JavaDoc) iter.next();
238                     final Set JavaDoc fileKeys = loadKeys(file);
239                     keys.addAll(fileKeys);
240                     fileMap.put(file, fileKeys);
241                 }
242
243                 // check the map for consistency
244
compareKeySets(keys, fileMap);
245             }
246         }
247     }
248
249
250     /**
251      * This method searches for property files in the specified file array
252      * and checks whether the key usage is consistent.
253      *
254      * Two property files which have the same prefix should use the same
255      * keys. If this is not the case the missing keys are reported.
256      *
257      * @param aFiles {@inheritDoc}
258      * @see com.puppycrawl.tools.checkstyle.api.FileSetCheck
259      */

260     public void process(File JavaDoc[] aFiles)
261     {
262         final File JavaDoc[] propertyFiles = filter(aFiles);
263         final Map JavaDoc propFilesMap = arrangePropertyFiles(propertyFiles);
264         checkPropertyFileSets(propFilesMap);
265     }
266
267
268
269 }
270
Popular Tags