/*
 * @(#)PackageRenamer.java	1.5 98/09/29
 * 
 * Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of Sun
 * Microsystems, Inc. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Sun.
 * 
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
 * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
 * THIS SOFTWARE OR ITS DERIVATIVES.
 * 
 * 
 */

import java.io.*;

/**
 * Program for changing the package name prefix strings for 
 * the Swing and Accessibility APIs from &quot;com.sun.java&quot; to
 * &quot;javax&quot; in the files specified on the command line. 
 * <p>
 * This should be used to convert Swing programs that were
 * written for Swing 1.0.X, Swing 1.1beta1, Swing 1.1beta2, or
 * JDK 1.2beta4, into usage for Swing1.1beta3, Swing1.1fcs,
 * and JDK 1.2fcs.
 * <p>
 * Note: This is NOT a generic search/replace utility, and is 
 * customized for the specific case of the Swing package name 
 * changes.
 * <p>
 * Example usage:
 * <pre><code>    java PackageRenamer Foo.java
 * </code></pre>
 * For each file specified on the command line which contains
 * strings to be replaced, the program will backup the original
 * contents into a file with the original name appended with
&quot;-old&quot;
 * and replace the original file with the modified version.
 */
public class PackageRenamer {

    protected static final int OLD = 0; // array index for "old"
string
    protected static final int NEW = 1; // array index for "new"
string
    protected static final int EXEMPT = 2; // starting array index for
                                           // exempt strings

    // Hardcode these for simplicity (no parsing data files)
    protected static String defaultSearchPrefix = "com.sun.java.";
    protected static String[][] defaultReplaceKeys = {
                             {"com.sun.java.swing",             // old 
                              "javax.swing",                    // new
                              "com.sun.java.swing.plaf.windows",//
exempt1 
                              "com.sun.java.swing.plaf.motif",  //
exempt2
                              "com.sun.java.swing.plaf.mac"},   //
exempt3

                             {"com.sun.java.accessibility",     // old 
                              "javax.accessibility",            // new
                              "com.sun.java.accessibility.util"}//
exempt
                              };

    protected String oldText;               // the original text
    protected StringBuffer newText;         // the modified text
    protected int changes;		    // the number of changes made

    protected static void usage() {
	System.err.println("java PackageRenamer " +
			   "<file1> [file2 ...]");
	System.exit(1);
    }

    protected static void error(String msg) {
	System.err.println(msg);
	System.exit(1);
    }

    public PackageRenamer() {
    }

    public int replace() {
        if (oldText == null) {
            error("text input not initialized");
        }
        newText = replaceStrings(oldText, defaultSearchPrefix,
defaultReplaceKeys);   
        return changes;
    }

     /* This method is designed to work for the specific
     * case where all the "old" strings being replaced
     * share a common search prefix, and each "old" string
     * may have a set of "exempt" cases which should NOT be 
     * replaced.
     */ 
    protected StringBuffer replaceStrings(String source, String
searchPrefix,
                                          String replaceKeys[][]) {
        StringBuffer result = new StringBuffer();

        int from = 0;       
        while(from < source.length()) {
            String replaceString = null;;
            int searchOffset = 0;
  
            // Search for occurrence of search prefix
            int index = source.indexOf(searchPrefix, from);
            if (index != -1) {
                // Found match on key prefix, 
                // loop to see if this further matches any
                // of the "old" strings
                replaceString = searchPrefix;
                searchOffset = searchPrefix.length();
                for (int i = 0; i < replaceKeys.length; i++) {
                    String oldString = replaceKeys[i][OLD];
                    if (source.regionMatches(index, oldString, 0, 
                                             oldString.length())) {
                        // Found match on "old" string,
                        // check to see if this further matches
                        // any of the "exempt" strings (which should
                        // NOT be replaced)
                        replaceString = replaceKeys[i][NEW];
                        searchOffset = replaceKeys[i][OLD].length();
                        changes++;
                        for (int k = EXEMPT; k <
replaceKeys[i].length; k++) {
                            String exempt = replaceKeys[i][k];
                            if (source.regionMatches(index, exempt, 0,
                                                     exempt.length())) {
                                // Found match on "exempt" string
                                replaceString = exempt;
                                searchOffset = exempt.length();
                                changes--;
                                break;
                            }
                        }
                        break;
                    }
                }
                // Append text preceding index of found string
                result.append(source.substring(from, index));

                // Append found or replacement string
                result.append(replaceString);

                // Move search index past found string, and
                // continue search...
                from = index + searchOffset;

           } else {
                // No occurrences of the key prefix were found
                result.append(source.substring(from));
                break; // we're done
           }
        }
        return result;
    }        


    public void load(File file) {
	try {
	    char[] chars = new char[(int)file.length()];
	    BufferedReader in = new BufferedReader(new FileReader(file));
	    in.read(chars);
	    in.close();
	    oldText = new String(chars);
	} catch (Exception e) {
	    error("failed reading " + file.getName() + ": " + e);
	}
    }

    public void save(File file) {
	try {
	    char[] chars = newText.toString().toCharArray();
	    BufferedWriter out = new BufferedWriter(new FileWriter(file));
	    out.write(chars);
	    out.close();
	} catch (IOException e) {
	    error("failed writing " + file.getName() + ": " + e);
	}
    }

    public static void main(String[] args) {
	int iArg = 0;
	int nArgs = args.length;
	if (nArgs == 0) {
	    usage();
	}

        // Load substitution file
        Reader reader = null;
        String filename;

	if (iArg == nArgs) {
	    error("no files specified");
	}

	for (; iArg < nArgs; iArg++) {
	    String fileName = args[iArg];
	    File file = new File(fileName);
	    if (!file.exists()) {
		System.err.println(fileName + " not found.");
		continue;
	    }

	    System.out.print(fileName + ": ");
	    System.out.flush();                                        

	    PackageRenamer renamer = new PackageRenamer();
	    renamer.load(file);
	    int changes = renamer.replace();
	    if (changes > 0) {
		// Save results to new file.
		File newFile = new File(fileName + "-new");
		renamer.save(newFile);

		// Delete previous -old file, if it exists.
		File oldFile = new File(fileName + "-old");
		if (oldFile.exists()) {
		    oldFile.delete();
		}

		// Rename original file to filename-old.
		file.renameTo(oldFile);

		// Rename new file to filename.
		newFile.renameTo(new File(fileName));
		System.out.println(Integer.toString(changes) +
		    ((changes > 1) ? " changes" : " change"));
	    } else {
                System.out.println("no changes");
            }
	}
    }
}
