

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

//------------------------ j2jClassx layer -------------------
//       encapsulates refinement of classes and anything
//       to do with their composition.  in this case, the j2j tool
//       requires some rewrites of classes *prior* to their
//       reduction.  Also, the j2j tool will be able to parse extensions
//       to classes, but will flag them as errors.

public class UmodClassDecl {

    String previous = "";

    public void harvestConstructors( int stage ) {

        // Step 0: do nothing if we are inside quoted text

        if ( stage != 0 ) {
            super.harvestConstructors( stage );
            return;
        }

        // Step 1: copy the inheritedCons of kernelConstants.j2jbase -- all the
        //         constructors we have seen up until now are 
        //         the constructors that we want to inherit

        copyConstructors();

        // Step 2: now harvest the constructors of the classBody
        //         this is where propagations of constructors UP
        //         the hierarchy can take place

        arg[3].harvestConstructors( stage );

        // Step 3: add reference to this type declaration

        kernelConstants.globals().j2jbase.previousTypeDecls.add( this );
    }

    private void finishReduction( AstProperties props ) {
        super.reduce2java( props );
        props.setProperty( "MixinDeclName", "" );
        props.setProperty( "SuperName", "" );
		  props.setProperty( "ThisName", previous );
    }

    public void reduce2java( AstProperties props ) {

        // Step 1: remember the name of the class that is being extended
        //         this is needed for correctly expanding Super() constructs
        //         inside static methods.

        String extendsName = "";
        ExtendsClause ec = ( ExtendsClause ) arg[1].arg[0];
        if ( ec != null )
            extendsName = ec.GetName();
        props.setProperty( "SuperName", extendsName );

        // Step 2: do a normal reduction if we haven't seen SoUrCe decls

        if ( props.getProperty( "SoUrCe" ) == null ) {
            finishReduction( props );
            return;
        }

        // Step 3: we could be reaching this reduction method because
        //         we have translated state machines or whatever into
        //         a class.  We don't perform double harvesting and
        //         rewriting, because this will generate errors.
        //         So if a non-null MixinDeclName is returned, we do
        //         nothing except a normal reduction
		  //         

        String name = ( String ) props.getProperty( "MixinDeclName" );
        if ( ! (name == null || name.equals( "" ) 
		          || (up instanceof NClassDecl) ) ) {
            finishReduction( props );
            return;
        }

        // Step 4: remember the name of the class that is being reduced
 
        String className = arg[0].tok[0].tokenName();
        props.setProperty( "MixinDeclName", className );
		  previous = (String) props.getProperty( "ThisName" );
		  if (previous == null) previous = "";
		  props.setProperty( "ThisName", Util2.unmangleId(className) );

        // Step 5: make sure that an FieldDecl is present

        if ( arg[3].arg[0].arg[0] == null ) {

            // can't set it because there is an empty ClassBody
            // so here's the hack -- we'll add an empty AST_FieldDecl
            // so that we can set its boolean

            arg[3].arg[0].Replace( new  AST_FieldDecl() );
        }
 
        // Step 6: add the ConstructorMarker

        AST_FieldDecl f = ( AST_FieldDecl ) arg[3].arg[0].arg[0];
        f.addMarker( inheritedCons );
  
        // Step 7: now reduce normally.  Clear refineSet as this
        //         keeps track of constructor refinements in this class.

        kernelConstants.globals().j2jbase.refinedSet.clear();

        // Step 8: finish the reduction

        finishReduction( props );
    }
}
