001/*
002 * Licensed under the Apache License, Version 2.0 (the "License");
003 * you may not use this file except in compliance with the License.
004 * You may obtain a copy of the License at
005 *
006 *     http://www.apache.org/licenses/LICENSE-2.0
007 *
008 * Unless required by applicable law or agreed to in writing, software
009 * distributed under the License is distributed on an "AS IS" BASIS,
010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011 * See the License for the specific language governing permissions and
012 * limitations under the License.
013 */
014package org.apache.wiki;
015
016import java.io.FileNotFoundException;
017import java.io.IOException;
018import java.util.ArrayList;
019import java.util.Collections;
020import java.util.Enumeration;
021import java.util.HashMap;
022import java.util.Iterator;
023import java.util.List;
024import java.util.Map;
025import java.util.Properties;
026import java.util.TreeSet;
027
028/**
029 * Simple utility that shows you a sorted list of property differences between
030 * the 'default en' and a given i18n file. It also warns if there are any duplicates.
031 * <p>
032 * The first argument is the language, and it is mandatory.
033 * The second argument is the path.  If the path is not defined, uses current path (.)
034 * <p>
035 * For example (if you're compiling your classes to "classes"):
036 * <code>
037 * java -cp classes TranslationsCheck fi
038 * </code>
039 *
040 */
041public class TranslationsCheck
042{
043    private static final TreeSet<String> allProps = new TreeSet<String>();  // sorted, no duplicates
044    private static final TreeSet<String> duplProps = new TreeSet<String>();
045
046    // Change these to your settings...
047    static String base = ".";
048    static String suffix = null;
049
050    public static void main(String[] args) throws IOException
051    {
052        if( args.length == 0 )
053        {
054            System.out.println("Usage: java TranslationsCheck <language> [<path>]");
055            System.out.println("Example: java TranslationsCheck nl [jspwiki-main/src/main/resources]");
056            return;
057        }
058
059        suffix = args[0];
060
061        if( args.length >= 2 )
062        {
063            base = args[1];
064        }
065
066        System.out.println("Using code base " + Release.VERSTR);
067        System.out.println("Internationalization property file differences between 'default en' and '" + suffix + "' following:\n");
068
069        try
070        {
071            diff("/CoreResources.properties", "/CoreResources_" + suffix + ".properties");
072            detectDuplicates("/CoreResources_" + suffix + ".properties");
073        }
074        catch( FileNotFoundException e )
075        {
076            System.err.println("Unable to locate "+"/CoreResources_" + suffix + ".properties");
077        }
078
079        try
080        {
081            diff("/templates/default.properties", "/templates/default_" + suffix + ".properties");
082            detectDuplicates("/templates/default_" + suffix + ".properties");
083        }
084        catch( FileNotFoundException e )
085        {
086            System.err.println("Unable to locate "+"/templates/default_" + suffix + ".properties");
087        }
088
089        try
090        {
091            diff("/plugin/PluginResources.properties", "/plugin/PluginResources_" + suffix + ".properties");
092
093            detectDuplicates("/plugin/PluginResources_" + suffix + ".properties");
094
095            System.out.println("Duplicates overall (two or more occurences):");
096            System.out.println("--------------------------------------------");
097            Iterator< String > iter = duplProps.iterator();
098            if (duplProps.size() == 0)
099                System.out.println("(none)");
100            else
101                while (iter.hasNext())
102                    System.out.println(iter.next());
103            System.out.println();
104        }
105        catch( FileNotFoundException e )
106        {
107            System.err.println("Unable to locate "+"/plugin/PluginResources_" + suffix + ".properties");
108        }
109
110        System.out.println("NOTE: Please remember that dependent on the usage of these i18n files, outdated " +
111                "properties maybe should not be deleted, because they may be used by previous releases. " +
112                "Moving them to a special section in the file may be the better solution.");
113    }
114
115    public static Map< String, Integer > diff(String source1, String source2) throws FileNotFoundException, IOException
116    {
117        int missing = 0, outdated = 0;
118        // Standard Properties
119        Properties p1 = new Properties();
120        
121        p1.load( TranslationsCheck.class.getClassLoader().getResourceAsStream( base + source1 ) );
122
123        Properties p2 = new Properties();
124        p2.load( TranslationsCheck.class.getClassLoader().getResourceAsStream( base + source2 ) );
125
126        String msg = "Checking " + source2 + "...";
127        System.out.println(msg);
128
129        Iterator< String > iter = sortedNames(p1).iterator();
130        while (iter.hasNext())
131        {
132            String name = iter.next();
133            String value = p1.getProperty(name);
134
135            if (p2.get(name) == null)
136            {
137                missing++;
138                if (missing == 1)
139                {
140                    System.out.println("\nMissing:");
141                    System.out.println("--------");
142                }
143                System.out.println(name + " = " + value);
144            }
145        }
146        if (missing > 0)
147        {
148            System.out.println();
149        }
150
151        iter = sortedNames(p2).iterator();
152        while (iter.hasNext())
153        {
154            String name = iter.next();
155            String value = p2.getProperty(name);
156
157            if (p1.get(name) == null)
158            {
159                outdated++;
160                if (outdated == 1)
161                {
162                    System.out.println("\nOutdated or superfluous:");
163                    System.out.println("------------------------");
164                }
165                System.out.println(name + " = " + value);
166            }
167        }
168        if (outdated > 0)
169        {
170            System.out.println();
171        }
172
173        Map< String, Integer > diff = new HashMap< String, Integer >( 2 );
174        diff.put( "missing", missing );
175        diff.put( "outdated", outdated );
176        return diff;
177    }
178
179    private static List<String> sortedNames(Properties p)
180    {
181        List<String> list = new ArrayList<String>();
182        Enumeration<?> iter = p.propertyNames();
183        while (iter.hasMoreElements())
184        {
185            list.add( (String)iter.nextElement() );
186        }
187
188        Collections.sort(list);
189        return list;
190    }
191
192    public static int detectDuplicates(String source) throws IOException
193    {
194        Properties p = new Properties();
195        p.load( TranslationsCheck.class.getClassLoader().getResourceAsStream( base + source ) );
196
197        Enumeration<?> iter = p.propertyNames();
198        String currentStr;
199        while (iter.hasMoreElements())
200        {
201            currentStr = (String) iter.nextElement();
202            if (!allProps.add(currentStr))
203                duplProps.add(currentStr);
204        }
205        return duplProps.size();
206    }
207
208}