

import java.util.*;
import Jakarta.util.FixDosOutputStream;
import java.io.*;

public class UmodClassDecl {

    // this method is called on parse tress of the SoUrCe file
    // the idea is for this method to propagate the contents of
    // this UmodClassDecl AST to the file referenced in the SoUrCe file.

    public void propagateChanges() {
        String myName = null;
        String referencedName = null;

        // Step 1: fetch the referenced file, parse it, and locate
        //         the lone ModTypeDecl declaration

        UnMixinUtil u = new  UnMixinUtil();

        // Step 2: do some error checking.  The ModTypeDecl must reference
        //         a UmodClassDecl or UmodClassExt with the same QName as 
        //         our parse tree

        //         note u.location is of type ModTypeDecl, whose first
        //         argument is an UnmodifiedTypeDeclaration -- in our
        //         case, it should be a UmodClassDecl

        if ( kernelConstants.globals().unmixin.base ) {
            // testing for UmodClassDecl

            if ( u.location.arg[1] instanceof  UmodClassDecl ) {
                referencedName = u.location.arg[1].arg[0].tok[0].tokenName();
                myName = arg[0].tok[0].tokenName();
                if ( !referencedName.equals( myName ) )
                    AstNode.fatalError( tok[0],
                                                 "expecting class " + myName + " but got "
                         + referencedName +
                         " file " + 
                                                              kernelConstants.globals().unmixin.fileName + 
                                                             " not updated" );
            }
            else
                AstNode.fatalError( tok[0],
                                "expecting UmodClassDecl but got " +
                        u.location.arg[1].getClass().getName() + 
                        " file " + 
                                                 kernelConstants.globals().unmixin.fileName + 
                                                " not updated" );
        }
        else {
            // testing for UmodClassExt

            if ( u.location.arg[1] instanceof  Ute &&
                u.location.arg[1].arg[0] instanceof  UmodClassExt ) {
                referencedName = u.location.arg[1].arg[0].arg[0].tok[0].tokenName();
                myName = arg[0].tok[0].tokenName();
                if ( !referencedName.equals( myName ) )
                    AstNode.fatalError( tok[0],
                                             "expecting class extension" + myName + 
                     " but got " + referencedName +
                     " file " + 
                                              kernelConstants.globals().unmixin.fileName + 
                                             " not updated" );
            }
            else
                AstNode.fatalError( tok[0],
                            "expecting Ute (or rather UmodClassExt) but got " +
                    u.location.arg[1].getClass().getName() + 
                    " file " + 
                                     kernelConstants.globals().unmixin.fileName + 
                                    " not updated" );
        }
  
        // Step 3: we're ready to make the changes!
        //         see if there is an extends clause -- there shouldn't
        //         be if a class appears to extend itself.  (This is 
        //         possible because of name mangling -- when names are
        //         unmangled, a class appears to extend itself).

        ExtendsClause k = ( ExtendsClause ) arg[1].arg[0];
        if ( k != null ) {
            String xname = ( ( AST_QualifiedName ) arg[1].arg[0].arg[0] ).GetName();
            if ( xname.equals( myName ) )
                k = null;
        }

        boolean updated = false;
        if ( kernelConstants.globals().unmixin.base )
            updated = ( ( UmodClassDecl ) u.location.arg[1] ).
               propagateChanges( k, ( ImplementsClause ) arg[2].arg[0], 
                                ( ClassBody ) arg[3] );
        else
            updated = ( ( UmodClassExt ) u.location.arg[1].arg[0] ).
               propagateChanges( ( ImplementsClause ) arg[2].arg[0], 
                                ( ClassBody ) arg[3] );

        // Step 4: last thing we do -- propagate the changes back to the file

        if ( updated )
            u.output();
    }

    // this method is called on the original AST, not the one with
    // SoUrCe declarations

    public boolean propagateChanges( ExtendsClause k,
                                     ImplementsClause i, 
                                     ClassBody b ) {
        // explicitly call to achieve side effects
        boolean u = oneChange( arg[1],k );
        u = oneChange( arg[2],i ) || u;
        u = oneChange( arg[3],b ) || u;
        return u;
    }

    public static boolean oneChange( AstNode old,  AstNode nu ) {
        boolean updated = false;
        if ( nu == null ) {
            if ( !old.toString().trim().equals( "" ) ) {
                old.Delete();
                updated = true;
            }
        }
        else {
            if ( nu!=null && ! ( old.toString().trim().equals( nu.toString().trim() ) ) ) {
                old.Replace( nu );
                updated = true;
            }
        }
        return updated;
    }
}
