

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

//---------------------- AST_FIELD declarations-------------------

public class AST_FieldDecl {

    // used for typeSorting and and in baseRewrites

    public  AstList makeList( AstNode n ) {
        if ( n instanceof  MethodDeclaration ) {
            n = ( AstNode ) n.clone();
        }

        AST_FieldDecl l = new  AST_FieldDecl();
        l.add( new  AST_FieldDeclElem().setParms( n ) );
        return l;
    }

    public void compose( AstNode etree ) {
        AstNode.fatalError( "don't invoke AST_FieldDecl.compose; use static" + 
                    " AST_FieldDecl.compose( AstNode etree, LinkedList ll )" );
    }

    // the following compose method is applied to a base node of
    // type AST_FieldDecl.  It has two parameters: the corresponding
    // AST_FieldDecl of the base AND a LinkedList of extension code
    // fragments that may have Base() references.  The trees in this 
    // vector are harvested from declarative specs (such as 
    // edge declarations in State Machine).  These trees are not
    // part of the extension code proper, but do belong there and
    // should be transformed just as if they were part of the 
    // extension AST_FieldDecl

    // part of the complexity of this method is that we blindly merged
    // the classbodies of the base and extension.  If the base was empty,
    // we substituted the ClassBody of the extensioin.  We can't quite
    // do this because we should check for errors in the extension 
    // itself.

    // FINALLY -- when you call this method, remember that it returns
    // the updated node.  so a call ALWAYS looks like:
    //    arg[?] = $TEqn.AST_FieldDecl( arg[?], ... , ... );
    // otherwise results aren't propagated!

    public static  AstNode compose( AstNode btree, 
                                           AstNode etree, LinkedList ll ) {
        ListIterator li = null;

        // Step 0: validate correct type

        AST_FieldDecl b = ( AST_FieldDecl ) btree;
        AST_FieldDecl e = ( AST_FieldDecl ) etree;
        if ( ll != null )
            li = ll.listIterator();

        // Step 1: collect signatures of all class member declarations
        //         in both the base and extension declarations

        Hashtable          hb = new Hashtable();
        Hashtable          he = new Hashtable();
        AstCursor     c = new  AstCursor();

        if ( b != null ) {
            for ( c.FirstElement( b ); c.MoreElement(); c.NextElement() ) {
                ( ( ClassBodyDeclaration ) c.node ).add2Hash( hb );
            }
        }

        if ( e != null ) {
            for ( c.FirstElement( e ); c.MoreElement(); c.NextElement() ) {
                ( ( ClassBodyDeclaration ) c.node ).add2Hash( he );
            }
        }

        // Step 2: invoke baseRewrite to rewrite all "Base(...).method(...)"
        //         invocations in the extension - both the extension proper
        //         and on the list itself

        if ( e != null )
            e.baseRewrite( hb, he, 0 );
        if ( li != null ) {
            while ( li.hasNext() ) {
                AstNode n = ( AstNode ) li.next();
                if ( n != null ) {
                    n.baseRewrite( hb, he, 0 );
                }
            }
        }

        // Step 3: now see if it is Ok to merge each element of the
        //         extension with the base

        Enumeration en = he.elements();
        for ( ; en.hasMoreElements(); ) {
            AstNode elem = ( AstNode ) en.nextElement();
            elem.ok2compose( 0, hb );
        }
         
        // Step 4: perform any cleanup activity on the base declarations

        if ( b != null )
            for ( c.FirstElement( b ); c.MoreElement(); c.NextElement() )
                ( ( ClassBodyDeclaration ) c.node ).cleanUpBase( c, he );
     
        // Step 5: return if both b and e are null, otherwise
        //         merge the extension and base Classbodies

        if ( b == null && e == null )
            return null;
        else
            if ( b != null && e != null )
                b.add( e );
            else
                if ( b == null )
                    b = e;
        // if e == null, use the current value of b which we know is nonnull

        // Step 6: optionally sort the declarations

        if ( Main.keySort ) {
            b = b.BodySort();
        }
        else
            if ( Main.typeSort )
                b.typeSort( new  AST_FieldDecl() );

        return b;
    }
}
