#!/bin/sh
# $Id: renamefiles 19240 2001-12-18 20:32:26Z cxh $
# Author: Christopher Hylands
#
# This script renames files.  It tries to fix the package and imports
# as well.  This script does not check the files into CVS.
#
# Typically, this script is run with the following commands:
#   cd $PTII/ptolemy/vergil
#   find . \( -name "*java*" -o -name "makefile" \) -exec rm {} \; ; cvs update
#   $PTII/adm/bin/renamefiles
#   make clean fast


# EDIT THE FILE NAMED by classesToMove
# This file contains the classes to move in the format
# foo.new.Bar  foo.old.Bif
# where foo.new.Bar is the new class and foo.old.Bif is the old class
#
classesToMove=$PTII/adm/bin/renamefiles.files

# maketemplate names the template makefile we use to create new makefiles.
maketemplate=$PTII/adm/bin/renamefiles.mk.in

# Hopefully, you need not edit below here.


####################################################################
# Sanity check the files to rename

# Check that the source files exist
sourceClasses=`awk '{print $2}' $classesToMove`
for sourceClass in $sourceClasses
do
    sourceFile=`echo $sourceClass | sed 's@\.@/@g'`
    sourceFullFile="$PTII/${sourceFile}.java"
    if [ ! -f $sourceFullFile ]; then
	# The rename function may have saved the source file as .old
	if [ ! -f ${sourceFullFile}.old ]; then
	    echo "$0: Error '$sourceFullFile' does not exist"
	    exit 5
	fi
    fi
done

####################################################################
echo "### Fixing up makefiles"
sourceClasses=`awk '{print $2}' $classesToMove`

for sourceClass in $sourceClasses
do
    sourceFile=`echo $sourceClass | sed 's@\.@/@g'`
    sourceMakefile=$PTII/`dirname $sourceFile`/makefile
    if [ ! -f $sourceMakefile ]; then
	echo "$0: WARNING: $sourceMakefile does not exist"
    else	
	echo "$sourceMakefile"
	sourceShortFile=`basename $sourceFile`.java
	grep -v $sourceShortFile $sourceMakefile > /tmp/renamefiles.tmp
	diff $sourceMakefile /tmp/renamefiles.tmp
	cp /tmp/renamefiles.tmp $sourceMakefile
    fi
done

####################################################################
echo "### Create the new makefiles if necessary, "
echo "###   using $maketemplate"
echo "### Add the new classes to the makefile if necessary"
destinationClasses=`awk '{print $1}' $classesToMove`

for destinationClass in $destinationClasses
do
    destinationFile=`echo $destinationClass | sed 's@\.@/@g'`
    destinationFullDir=$PTII/`dirname $destinationFile`
    if [ ! -d $destinationFullDir ]; then
	mkdir $destinationFullDir
    fi
    destinationMakefile=$destinationFullDir/makefile
    if [ ! -f $destinationMakefile ]; then
	echo "Creating $destinationMakefile"
	destinationDir=`dirname $destinationFile`	
	basedir=`basename $destinationDir`
	sed -e "s=@dir@=$destinationDir=g" \
	    -e "s=@basedir@=$basedir=g" \
            < $maketemplate > $destinationMakefile
    fi	    
    echo "$destinationMakefile"
    destinationShortFile=`basename $destinationFile`.java
    grep $destinationShortFile $destinationMakefile > /tmp/renamefiles.tmp
    retval=$?
    if [ $retval = 0 ]; then
	echo "$destinationMakefile already contains $destinationShortFile"
    else    
    # FIXME: these are not in alphabetical order
    awk '{if ( $0 ~ /^JSRCS/ ) {
		    print $0
		    print "	" destinationShortFile " \\"
		  } else {   
		    print $0
		  }
		}' destinationShortFile=${destinationShortFile} \
		 $destinationMakefile > /tmp/renamefiles.tmp

    diff $destinationMakefile /tmp/renamefiles.tmp
    cp /tmp/renamefiles.tmp $destinationMakefile
    fi
done

####################################################################
# Create copies of the class files

# The sed script generated by running the rename proc below.
# Each time we run the rename proc, we add sed commands to this line. 
sedScript=/tmp/renamefiles-sedScript

# Rename a file and change the package
# Usage: rename vergil.new.Foo vergil.old.Bar
# This is a shell procedure that gets called later, once for each
# rename operation.
rename() {
    destinationClass=$1
    sourceClass=$2

    echo $1
    # Directory and Filename without the .java
    destinationFile=`echo $destinationClass | sed 's@\.@/@g'`
    sourceFile=`echo $sourceClass | sed 's@\.@/@g'`

    destinationFullFile="$PTII/${destinationFile}.java"
    sourceFullFile="$PTII/${sourceFile}.java"

    if [ ! -f $sourceFullFile ]; then
	if [ ! -f ${sourceFullFile}.old ]; then
	    echo "$0: WARNING $sourceFullFile  does not exist"
	    return
	else 
	    sourceFullFile=${sourceFullFile}.old
	fi    
    else
	mv $sourceFullFile ${sourceFullFile}.old
	sourceFullFile=${sourceFullFile}.old
    fi 

    destinationDir=`dirname $destinationFile`
    sourceDir=`dirname $sourceFile`

    destinationPackage=`echo $destinationDir | sed 's@/@.@g'`
    sourcePackage=`echo $sourceDir | sed 's@/@.@g'`

    destinationShortClass=`basename $destinationFile`
    sourceShortClass=`basename $sourceFile`

    # Change any imports before changing the class names themselves
    echo "s/$sourceClass/$destinationClass/g" \
	    >> $sedScript

    if [ $sourceShortClass != $destinationShortClass ]; then
	# Build up a sed script for later use.

	# We use [^a-zA-Z] to deal with class names that are
	# subsets of longer classnames.  If FooBar is the class
	# and we are changing both FooBar to Bif and 
        # MyFooBar to Baz, then we dont want to end up with MyBif
	# by first doing FooBar->Bif.
	echo "s/\([^a-zA-Z]\)$sourceShortClass\([^a-zA-Z]\)/\1$destinationShortClass\2/g" \
	    >> $sedScript

	# Handle classes that are at the end of the line.
	echo "s/\([^a-zA-Z]\)$sourceShortClass$/\1$destinationShortClass/g" \
	    >> $sedScript
    fi	

    sed "s@$sourcePackage@$destinationPackage@" \
	< $sourceFullFile > $destinationFullFile

#      if [ $destinationPackage != $sourcePackage ]; then
#  	# Moving packages, so add an import for the old package
#  	              awk '{  if ($0 ~ /^package/) {
#  				print $0
#  				sawPackage=1
#  			    } else {
#  				if (sawPackage == 1) {
#  				    print $0
#  				    print "import", sourcePackage ".*; // FIXME: This class was moved from this package, so we might not need the import"
#  				    sawPackage = 0
#  				} else {
#  				    print $0
#  				}
#  			    }
#  		    }' sourcePackage=${sourcePackage} \
#  			$destinationFullFile > /tmp/renamefiles.tmp
#  		    #diff $destinationFullFile /tmp/renamefiles.tmp
#  		    cp /tmp/renamefiles.tmp $destinationFullFile 
#      fi
}

# The sedScript is updated when we run rename, we remove the sedScript file
# because we want to start from a fresh slate when we run rename over
# and over again below. 
rm -f $sedScript

# Uncomment the next two lines for testing purposes
#rename ptolemy.vergil.actor.ActorGraphFrame ptolemy.vergil.ptolemy.kernel.KernelGraphFrame
#exit

# Read in the files to be converted and generate a script.
renameScript=/tmp/renamefiles-renameScript
awk '{print "rename", $1, $2}' $classesToMove >  $renameScript

echo "### Generating new files"

# The . runs the script in this context
. $renameScript

####################################################################
echo "### Doing substitutions in $PTII/ptolemy/vergil"

javaFiles=`find $PTII/ptolemy/vergil -name "*.java" -print`
for javaFile in $javaFiles
do
    echo "$javaFile"
    sed -f $sedScript < $javaFile > /tmp/renamefiles.tmp
    diff $javaFile /tmp/renamefiles.tmp
    cp /tmp/renamefiles.tmp $javaFile 
done

    
####################################################################
echo "### Fixing up imports"

# If a file contains one of the new classes and it does not
# have an import and it is not in the same package where the 
# new directory resides, then we add an import.

# Generate a regular expression that contains all the new classnames.
# We use this to speed up the search for possible classes that we 
# should add imports to.
classregex=`awk '{nf = split($1,f,"."); 
		    if (NR == 1) {
			printf("%s",f[nf])
		    } else {	
			printf("|%s",f[nf])
		    }
		}' $classesToMove `

echo "classregex=$classregex"

newClasses=`awk '{print $1}' $classesToMove`
for javaFile in $javaFiles
do
    echo "$javaFile"
    egrep "$classregex" $javaFile
    retval=$?
    if [ $retval = 1 ]; then
	echo "$javaFile does not contain one of the moved classes"
    else
    for newClass in $newClasses
    do
	echo "$newClass"
	package=`egrep "^package" $javaFile | awk '{print substr($2,1,length($2)-1)}'`
	newPackage=`echo $newClass | awk -F . '{ printf("%s", $1);
		    for(i=2;i<NF;i++) {printf(".%s",$i)}}'`
	if [ $package = $newPackage ]; then
	    echo "skipping $javaFile it is in the same package as $newClass"
	else
	    egrep "import $newPackage.\*;" $javaFile
	    retval=$?
	    if [ $retval = 0 ]; then
		echo "skipping $javaFile, it contains import $newPackage.*;"
	    else
		newShortClass=`echo $newClass | awk -F . '{print $NF}'`
		egrep "[^a-zA-Z]$newShortClass[^a-zA-Z]" $javaFile
		retval=$?
		if [ $retval = 0 ]; then
		    echo "$javaFile needs to import $newClass"
		    # FIXME: the imports are not added in the proper
		    # alphabetical order.  We should probably post process
		    # these.
		    awk '{  if ($0 ~ /^package/) {
				print $0
				sawPackage=1
			    } else {
				if (sawPackage == 1) {
				    print $0
				    print "import", newClass ";"
				    sawPackage = 0
				} else {
				    print $0
				}
			    }
		    }' newClass=${newClass} $javaFile > /tmp/renamefiles.tmp
		    diff $javaFile /tmp/renamefiles.tmp		    
		    cp /tmp/renamefiles.tmp $javaFile		    
		fi
	    fi	
	fi
    done
    fi
done
