// **********************************************************************
//
// Copyright (c) 1999
// Object Oriented Concepts, Inc.
// Billerica, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#include <OB/CORBA.h>
#include <Types.h>
#include <Util.h>
#include <GenUtil.h>

#ifdef HAVE_FSTREAM
#   include <fstream>
#else
#   include <fstream.h>
#endif

#include <GenJava.h>

// ----------------------------------------------------------------------
// Generate Java code
// ----------------------------------------------------------------------

int
IdlJavaGenerator::genJava(CORBA_Container_ptr container, IdlPrettyPrint& out)
{
    //
    // Get container contents descriptions
    //
    CORBA_Container::DescriptionSeq_var seq =
	container -> describe_contents(CORBA_dk_all, true, -1);

    CORBA_ULong i, j, k;

    int status = 0;
    for(i = 0 ; status == 0 && i < seq -> length() ; i++)
    {
	//
	// Get container
	//
	CORBA_Container_var cont =
	    CORBA_Container::_narrow(seq[i].contained_object);

	switch(seq[i].kind)
	{
	case CORBA_dk_Constant:
	{
	    //
	    // Constant
	    //
	    CORBA_ConstantDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    if(!check(desc -> id))
		continue;

	    CORBA_Identifier_var name = fixName(desc -> name);
	    CORBA_String_var package = getPackage(desc -> id);

	    //
	    // Constants declared within an interface are mapped to a
	    // static member, all other constants are mapped to a separate
	    // class.
	    //
	    if(container -> def_kind() != CORBA_dk_Interface)
	    {
		PrettyPrint out(fileNameSeq_, prog_, name, package, outDir_);
		if(!out.good())
		    return 1;

		comment(desc -> id, out);
		docComment(desc -> id, out);

		out.sep();
		out << "\npublic interface " << name;
		out.start();
		CORBA_String_var norm = getTypeString(package, desc -> type);
		out << "\npublic static final " << norm
		    << " value = ";
		writeConstant(desc -> value, out);
		out << ';';
		out.end();
	    }
	    else
	    {
		comment(desc -> id, out);
		docComment(desc -> id, out);

		CORBA_String_var norm = getTypeString(package, desc -> type);
		out.sep();
		out << "\npublic static final " << norm
		    << ' ' << name << " = ";
		writeConstant(desc -> value, out);
		out << ';';
	    }

	    break;
	}

	case CORBA_dk_Module:
	{
	    //
	    // Module
	    //
	    CORBA_ModuleDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    // Don't add this here!!!
	    // if(!check(desc -> id))
	    //     continue;

	    assert(!CORBA_is_nil(cont));
	    status = genJava(cont, out);

	    break;
	}

	case CORBA_dk_Interface:
	{
	    //
	    // Interface
	    //
	    CORBA_InterfaceDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    if(!check(desc -> id))
		continue;

	    CORBA_Identifier_var name = fixName(desc -> name);
	    CORBA_String_var package = getPackage(desc -> id);

	    unsigned int indent;

	    //
	    // Interface for the interface
	    //
	    PrettyPrint out(fileNameSeq_, prog_, name, package, outDir_);
	    if(!out.good())
		return 1;
	    
	    comment(desc -> id, out);
	    docComment(desc -> id, out);

	    out.sep();
	    out << "\npublic interface " << name << " extends ";

	    indent = out.getIndent();
	    out.setIndent(out.getPos());

	    if(desc -> base_interfaces.length() > 0)
	    {
		for(j = 0 ; j < desc -> base_interfaces.length() ; j++)
		{
		    const char* id = desc -> base_interfaces[j];
		    CORBA_ScopedName_var absolute = getAbsolute(id);
		    removePackage(package, absolute.inout());

		    if(j > 0)
			out << ",\n";

		    out << absolute;
		}
	    }
	    else
		out << "org.omg.CORBA.Object";

	    out.setIndent(indent);

	    out.start();
	    status = genJava(cont, out);
	    out.end();

	    //
	    // Stub for the interface
	    //
	    CORBA_InterfaceDef_var interf =
		CORBA_InterfaceDef::_narrow(seq[i].contained_object);
	    assert(!CORBA_is_nil(interf));
		
	    if(!local_)
	    {
		CORBA_String_var stub = CORBA_string_dup("StubFor");
		stub += name;
		PrettyPrint outStub(fileNameSeq_, prog_, stub, package,
				    outDir_);
		if(!outStub.good())
		    return 1;

		comment(desc -> id, outStub);

		outStub.sep();
		outStub << "\npublic class " << stub << ' ';
		indent = outStub.getIndent();
		outStub.setIndent(outStub.getPos());
		outStub << "extends org.omg.CORBA.portable.ObjectImpl";
		outStub << "\nimplements " << name;
		outStub.setIndent(indent);

		outStub.start();

		CORBA_ContainedSeq_var attributes =
		    interf -> contents(CORBA_dk_Attribute, false);

		CORBA_ContainedSeq_var operations =
		    interf -> contents(CORBA_dk_Operation, false);

		CORBA_InterfaceDefSeq allBaseInterfaces;
		IdlGetAllBaseInterfaces(interf, allBaseInterfaces);

		outStub << "\nstatic final String[] _ob_ids_ =";
		outStub.start();
		outStub << "\n\"" << desc -> id << "\",";
		for(j = 0 ; j < allBaseInterfaces.length() ; j++)
		{
		    CORBA_RepositoryId_var id =
			allBaseInterfaces[j] -> id();
		    outStub << "\n\"" << id << '"';
		    if(j + 1 < allBaseInterfaces.length())
			outStub << ',';
		}
		outStub.end();
		outStub << ';';

		outStub.sep();
		outStub << "\npublic String[]\n_ids()";
		outStub.start();
		outStub << "\nreturn _ob_ids_;";
		outStub.end();

		for(j = 0 ; j < attributes -> length() ; j++)
		{
		    CORBA_Contained::Description_var contDesc =
			attributes[j] -> describe();
		    CORBA_AttributeDescription* atDesc;
		    CORBA_Boolean b = (contDesc -> value) >>= atDesc;
		    assert(b);

		    CORBA_Identifier_var atName = fixName(atDesc -> name);

		    comment(atDesc -> id, outStub);

		    CORBA_String_var result =
			getTypeString(package, atDesc -> type);
		    outStub.sep();
		    outStub << "\npublic " << result << '\n' << atName << "()";

		    outStub.start();

		    outStub << "\norg.omg.CORBA.Request _ob_req = "
			    << "_request(\"_get_" << atDesc -> name << "\");";

		    outStub.sep();
		    outStub << "\n_ob_req.set_return_type(";
		    writeTypeCode("_orb()", package, atDesc -> type, outStub);
		    outStub << ");";

		    outStub.sep();
		    outStub << "\n_ob_req.invoke();";

		    outStub.sep();
		    outStub << "\njava.lang.Exception _ob_ex = "
			    << "_ob_req.env().exception();";
		    outStub << "\nif(_ob_ex != null)";
		    outStub.inc();
		    outStub << "\nthrow (org.omg.CORBA.SystemException)"
			    << "_ob_ex;";
		    outStub.dec();

		    outStub.sep();
		    outStub << "\norg.omg.CORBA.Any _ob_ra"
			    << " = _ob_req.return_value();";
		    outStub << "\nreturn ";
		    writeInsertExtract(package, atDesc -> type, "_ob_ra", true,
				       outStub);
		    outStub << ';';

		    outStub.end();

		    if(atDesc -> mode == CORBA_ATTR_NORMAL)
		    {
			outStub.sep();
			outStub << "\npublic void\n" << atName << '('
				<< result << " _ob_a)";

			outStub.start();

			outStub << "\norg.omg.CORBA.Request _ob_req = "
				<< "_request(\"_set_"
				<< atDesc -> name << "\");";

			outStub.sep();
			outStub << "\norg.omg.CORBA.Any _ob_aa = "
				<< "_ob_req.add_in_arg();";
			outStub << '\n';
			writeInsertExtract(package, atDesc -> type, "_ob_aa",
					   false, outStub);
			outStub << "_ob_a);";

			outStub.sep();
			outStub << "\n_ob_req.invoke();";

			outStub.sep();
			outStub << "\njava.lang.Exception _ob_ex = "
				<< "_ob_req.env().exception();";
			outStub << "\nif(_ob_ex != null)";
			outStub.inc();
			outStub << "\nthrow (org.omg.CORBA.SystemException)"
				<< "_ob_ex;";
			outStub.dec();

			outStub.end();
		    }
		}

		for(j = 0 ; j < operations -> length() ; j++)
		{
		    CORBA_Contained::Description_var contDesc =
			operations[j] -> describe();
		    CORBA_OperationDescription* opDesc;
		    CORBA_Boolean b = (contDesc -> value) >>= opDesc;
		    assert(b);

		    CORBA_Identifier_var opName = fixName(opDesc -> name);

		    comment(opDesc -> id, outStub);

		    bool haveOutOrInOut = false;

		    CORBA_TypeCode_var origRet =
			OBGetOrigType(opDesc -> result);

		    CORBA_String_var result = getTypeString(package, origRet);
		    outStub.sep();
		    outStub << "\npublic " << result << '\n' << opName << "(";

		    unsigned int indent = outStub.getIndent();
		    outStub.setIndent(outStub.getPos());

		    for(k = 0 ; k < opDesc -> parameters.length() ; k++)
		    {
			if(k > 0)
			    outStub << ",\n";

			switch(opDesc -> parameters[k].mode)
			{
			case CORBA_PARAM_IN:
			{
			    CORBA_String_var str =
				getTypeString(package,
					      opDesc -> parameters[k].type);
			    outStub << str << " _ob_a" << k;
			    break;
			}

			case CORBA_PARAM_INOUT:
			case CORBA_PARAM_OUT:
			{
			    CORBA_String_var str =
				getTypeString(package,
					      opDesc -> parameters[k].type,
					      GetTypeHolder);
			    outStub << str << " _ob_ah" << k;
			    haveOutOrInOut = true;
			    break;
			}
			}
		    }

		    if(opDesc -> contexts.length() > 0)
		    {
			if(opDesc -> parameters.length() > 0)
			    outStub << ",\n";

			outStub << "org.omg.CORBA.Context _ob_ctx";
		    }

		    outStub.setIndent(indent);

		    outStub << ')';

		    if(opDesc -> exceptions.length())
		    {
			outStub.inc();
			outStub << "\nthrows ";

			unsigned int indent = outStub.getIndent();
			outStub.setIndent(outStub.getPos());

			for(k = 0 ; k < opDesc -> exceptions.length() ; k++)
			{
			    if(k)
				outStub << ",\n";

			    CORBA_String_var str =
				getTypeString(package,
					      opDesc -> exceptions[k].type);

			    outStub << str;
			}

			outStub.setIndent(indent);
			outStub.dec();
		    }

		    outStub.start();

		    outStub << "\norg.omg.CORBA.Request _ob_req = _request(\""
			    << opDesc -> name << "\");";

		    for(k = 0 ; k < opDesc -> exceptions.length() ; k++)
		    {
			if(k == 0)
			    outStub.sep();

			CORBA_String_var str =
			    getTypeString(package,
					  opDesc -> exceptions[k].type,
					  GetTypeHelper);

			outStub << "\n_ob_req.exceptions().add(" << str
				<< ".type());";
		    }

		    for(k = 0 ; k < opDesc -> parameters.length() ; k++)
		    {
			if(k == 0)
			    outStub.sep();

			switch(opDesc -> parameters[k].mode)
			{
			case CORBA_PARAM_IN:
			{
			    outStub << "\norg.omg.CORBA.Any _ob_aa" << k
				    << " = _ob_req.add_in_arg();";
			    CORBA_String_var any = CORBA_string_dup("_ob_aa");
			    any += k;
			    outStub << '\n';
			    writeInsertExtract(package,
					       opDesc -> parameters[k].type,
					       any, false, outStub);
			    outStub << "_ob_a" << k << ");";
			    break;
			}

			case CORBA_PARAM_INOUT:
			{
			    outStub << "\norg.omg.CORBA.Any _ob_aa" << k
				    << " = _ob_req.add_inout_arg();";
			    CORBA_String_var any = CORBA_string_dup("_ob_aa");
			    any += k;
			    outStub << '\n';
			    writeInsertExtract(package,
					       opDesc -> parameters[k].type,
					       any, false, outStub);
			    outStub << "_ob_ah" << k << ".value);";
			    break;
			}

			case CORBA_PARAM_OUT:
			{
			    outStub << "\norg.omg.CORBA.Any _ob_aa" << k
				    << " = _ob_req.add_out_arg();";
			    outStub << "\n_ob_aa" << k << ".type(";
			    writeTypeCode("_orb()", package,
					  opDesc -> parameters[k].type,
					  outStub);
			    outStub << ");";
			    break;
			}
			}
		    }

		    if(opDesc -> contexts.length() > 0)
		    {
			outStub.sep();
			for(k = 0 ; k < opDesc -> contexts.length() ; k++)
			{
			    outStub << "\n_ob_req.contexts().add(\"";
			    outStub << opDesc -> contexts[k];
			    outStub << "\");";
			}
			outStub << "\n_ob_req.ctx(_ob_ctx);";
		    }

		    if(origRet -> kind() != CORBA_tk_void)
		    {
			outStub.sep();
			outStub << "\n_ob_req.set_return_type(";
			writeTypeCode("_orb()", package,
				      opDesc -> result, outStub);
			outStub << ");";
		    }

		    outStub.sep();
		    if(opDesc -> mode == CORBA_OP_ONEWAY)
			outStub << "\n_ob_req.send_oneway();";
		    else
			outStub << "\n_ob_req.invoke();";

                    outStub.sep();
                    outStub << "\njava.lang.Exception _ob_ex = "
                            << "_ob_req.env().exception();";
                    outStub << "\nif(_ob_ex != null)";
		    if(opDesc -> exceptions.length() > 0)
		    {
			outStub.start();
                        outStub << "\nif(_ob_ex instanceof "
			        << "org.omg.CORBA.UnknownUserException)";
                        outStub.start();
			outStub << "\norg.omg.CORBA.UnknownUserException "
				<< "_ob_uex = (org.omg.CORBA."
                                << "UnknownUserException)_ob_ex;";
                        outStub << "\norg.omg.CORBA.TypeCode _ob_tc = "
                                << "_ob_uex.except.type();";
			outStub.sep();
			for(k = 0 ; k < opDesc -> exceptions.length() ; k++)
			{
			    CORBA_String_var strHelper =
				getTypeString(package,
					      opDesc -> exceptions[k].type,
					      GetTypeHelper);

                            outStub << "\nif(_ob_tc.equals(" << strHelper
                                    << ".type()))";
                            outStub.inc();
                            outStub << "\nthrow " << strHelper
                                    << ".extract(_ob_uex.except);";
                            outStub.dec();
			}
			outStub.sep();
			outStub << "\nthrow new org.omg.CORBA.UNKNOWN();";
			outStub.end();
                        outStub << "\nelse";
			outStub.inc();
			outStub << "\nthrow (org.omg.CORBA.SystemException)"
                                << "_ob_ex;";
			outStub.dec();
			outStub.end();
		    }
                    else
                    {
			outStub.inc();
			outStub << "\nthrow (org.omg.CORBA.SystemException)"
                                << "_ob_ex;";
			outStub.dec();
                    }

		    if(haveOutOrInOut)
			outStub.sep();

		    for(k = 0 ; k < opDesc -> parameters.length() ; k++)
		    {
			if(opDesc -> parameters[k].mode != CORBA_PARAM_IN)
			{
			    CORBA_String_var any = CORBA_string_dup("_ob_aa");
			    any += k;
			    outStub << "\n_ob_ah" << k << ".value = ";
			    writeInsertExtract(package,
					       opDesc -> parameters[k].type,
					       any, true, outStub);
			    outStub << ';';
			}
		    }

		    if(origRet -> kind() != CORBA_tk_void)
		    {
			outStub.sep();
			outStub << "\norg.omg.CORBA.Any _ob_ra"
				<< " = _ob_req.return_value();";
			outStub << "\nreturn ";
			writeInsertExtract(package, opDesc -> result, "_ob_ra",
					   true, outStub);
			outStub << ';';
		    }

		    outStub.end();
		}

		outStub.end();
	    }

	    //
	    // Write the holder class
	    //
	    CORBA_String_var holder = name;
	    holder += "Holder";
	    PrettyPrint outHolder(fileNameSeq_, prog_, holder, package,
				  outDir_);
	    if(!outHolder.good())
		return 1;
	    
	    comment(desc -> id, outHolder);

	    writeHolder(name, name, outHolder);

	    //
	    // Write the helper class
	    //
//	    if(!local_)
	    {
		CORBA_String_var helper = name;
		helper += "Helper";
		PrettyPrint outHelper(fileNameSeq_, prog_, helper, package,
				      outDir_);
		if(!outHelper.good())
		    return 1;
		
		comment(desc -> id, outHelper);

		CORBA_TypeCode_var type = interf -> type();
		writeHelper(package, type, outHelper);
	    }

	    break;
	}

	case CORBA_dk_Alias:
	{
	    //
	    // Alias
	    //
	    CORBA_TypeDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    if(!check(desc -> id))
		continue;

	    CORBA_Identifier_var name = fixName(desc -> name);
	    CORBA_String_var package = getPackage(desc -> id);

	    //
	    // Write the holder class only for sequence and array typedefs
	    //
	    CORBA_TypeCode_var origType = OBGetOrigType(desc -> type);
	    if(origType -> kind() == CORBA_tk_array ||
	       origType -> kind() == CORBA_tk_sequence)
	    {
		CORBA_String_var holder = name;
		holder += "Holder";
		PrettyPrint outHolder(fileNameSeq_, prog_, holder, package,
				      outDir_);
		if(!outHolder.good())
		    return 1;
		
		comment(desc -> id, outHolder);
		
		CORBA_String_var norm = getTypeString(package, desc -> type);
		writeHolder(norm, name, outHolder);
	    }

	    //
	    // Write the helper class
	    //
//	    if(!local_)
	    {
		CORBA_String_var helper = name;
		helper += "Helper";
		PrettyPrint outHelper(fileNameSeq_, prog_, helper, package,
				      outDir_);
		if(!outHelper.good())
		return 1;
		
		comment(desc -> id, outHelper);
		
		writeHelper(package, desc -> type, outHelper);
	    }

	    break;
	}

	case CORBA_dk_Enum:
	{
	    //
	    // Enum
	    //
	    CORBA_TypeDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    if(!check(desc -> id))
		continue;

	    CORBA_Identifier_var name = fixName(desc -> name);
	    CORBA_String_var package = getPackage(desc -> id);

	    PrettyPrint out(fileNameSeq_, prog_, name, package, outDir_);
	    if(!out.good())
		return 1;

	    comment(desc -> id, out);
	    docComment(desc -> id, out);

	    out.sep();
	    out << "\nfinal public class " << name;
	    out.start();

	    out << "\nprivate static " << name << " [] values_ = new "
		<< name << "[" << desc -> type -> member_count() << "];";
	    out << "\nprivate int value_;";
	    out.sep();

	    for(j = 0 ; j < desc -> type -> member_count() ; j++)
	    {
		CORBA_Identifier_var memberName =
		    desc -> type -> member_name(j);
		memberName = fixName(memberName);
		out << "\npublic final static int _" << memberName
		    << " = " << j << ";";
		out << "\npublic final static " << name << " " << memberName
		    << " = new " << name << "(_" << memberName << ");";
	    }

	    out.sep();
	    out << "\nprotected\n" << name << "(int value)";
	    out.start();
	    out << "\nvalues_[value] = this;";
	    out << "\nvalue_ = value;";
	    out.end();

	    out.sep();
	    out << "\npublic int\nvalue()";
	    out.start();
	    out << "\nreturn value_;";
	    out.end();

	    out.sep();
	    out << "\npublic static " << name << "\nfrom_int(int value)";
	    out.start();
	    out << "\nreturn values_[value];";
	    out.end();

	    if(clone_)
		writeClone(seq[i].kind, name, package, desc -> type, out);

	    out.end();

	    //
	    // Write the holder class
	    //
	    CORBA_String_var holder = name;
	    holder += "Holder";
	    PrettyPrint outHolder(fileNameSeq_, prog_, holder, package,
				  outDir_);
	    if(!outHolder.good())
		return 1;
	    
	    comment(desc -> id, outHolder);
	    
	    writeHolder(name, name, outHolder);

	    //
	    // Write the helper class
	    //
//	    if(!local_)
	    {
		CORBA_String_var helper = name;
		helper += "Helper";
		PrettyPrint outHelper(fileNameSeq_, prog_, helper, package,
				      outDir_);
		if(!outHelper.good())
		    return 1;

		comment(desc -> id, outHelper);

		writeHelper(package, desc -> type, outHelper);
	    }

	    break;
	}

	case CORBA_dk_Struct:
	case CORBA_dk_Exception:
	{
	    CORBA_RepositoryId_var id;
	    CORBA_Identifier_var name;
	    CORBA_TypeCode_var type;
	    
	    if(seq[i].kind == CORBA_dk_Struct)
	    {
		//
		// Struct
		//
		CORBA_TypeDescription* desc;
		CORBA_Boolean b = seq[i].value >>= desc;
		assert(b);

		name = fixName(desc -> name);
		id = desc -> id;
		type = desc -> type;
	    }
	    else
	    {
		//
		// Exception
		//
		CORBA_ExceptionDescription* desc;
		CORBA_Boolean b = seq[i].value >>= desc;
		assert(b);

		name = fixName(desc -> name);
		id = desc -> id;
		type = desc -> type;
	    }

	    if(!check(id))
		continue;

	    CORBA_String_var package = getPackage(id);

	    PrettyPrint out(fileNameSeq_, prog_, name, package, outDir_);
	    if(!out.good())
		return 1;

	    comment(id, out);
	    docComment(id, out);

	    out.sep();
	    out << "\nfinal public class " << name;
	    if(seq[i].kind == CORBA_dk_Exception)
		out << " extends org.omg.CORBA.UserException";

	    out.start();

	    out << "\npublic\n" << name << "()";
	    out.start();
	    out.end();

	    if(type -> member_count() > 0)
	    {
		out.sep();
		out << "\npublic\n" << name << "(";
		unsigned int indent = out.getIndent();
		out.setIndent(out.getPos());
		for(j = 0 ; j < type -> member_count() ; j++)
		{
		    CORBA_TypeCode_var memberType = type -> member_type(j);
		    CORBA_String_var norm = getTypeString(package, memberType);

		    if(j)
			out << ",\n";

		    out << norm << " _ob_a" << j;
		}
		out << ")";
		out.setIndent(indent);

		out.start();
		for(j = 0 ; j < type -> member_count() ; j++)
		{
		    CORBA_TypeCode_var memberType = type -> member_type(j);
		    CORBA_Identifier_var memberName = type -> member_name(j);
		    memberName = fixName(memberName);

		    out << "\n" << memberName << " = _ob_a" << j << ';';
		}
		out.end();
	    }

	    if(clone_)
		writeClone(seq[i].kind, name, package, type, out);

	    for(j = 0 ; j < type -> member_count() ; j++)
	    {
		CORBA_TypeCode_var memberType = type -> member_type(j);
		CORBA_Identifier_var memberName = type -> member_name(j);
		memberName = fixName(memberName);

		CORBA_String_var norm = getTypeString(package, memberType);

		if(j == 0)
		    out.sep();

		out << "\npublic " << norm << ' ' << memberName << ";";
	    }

	    out.end();

	    //
	    // Write the holder class
	    //
	    CORBA_String_var holder = name;
	    holder += "Holder";
	    PrettyPrint outHolder(fileNameSeq_, prog_, holder, package,
				  outDir_);
	    if(!outHolder.good())
		return 1;
	    
	    comment(id, outHolder);
	    
	    writeHolder(name, name, outHolder);

	    //
	    // Write the helper class
	    //
//	    if(!local_)
	    {
		CORBA_String_var helper = name;
		helper += "Helper";
		PrettyPrint outHelper(fileNameSeq_, prog_, helper, package,
				      outDir_);
		if(!outHelper.good())
		    return 1;

		comment(id, outHelper);

		writeHelper(package, type, outHelper);
	    }

	    break;
	}

	case CORBA_dk_Union:
	{
	    //
	    // Union
	    //
	    CORBA_TypeDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    if(!check(desc -> id))
		continue;

	    CORBA_Identifier_var name = fixName(desc -> name);
	    CORBA_String_var package = getPackage(desc -> id);

	    CORBA_TypeCode_var discType = desc -> type -> discriminator_type();
	    CORBA_TypeCode_var origDiscType = OBGetOrigType(discType);
	    CORBA_String_var disc = getTypeString(package, origDiscType);
	    CORBA_String_var intDisc;
	    if(origDiscType -> kind() == CORBA_tk_enum ||
	       origDiscType -> kind() == CORBA_tk_boolean)
		intDisc = CORBA_string_dup("int");
	    else
		intDisc = disc;

	    PrettyPrint out(fileNameSeq_, prog_, name, package, outDir_);
	    if(!out.good())
		return 1;

	    IdlUnionMemberInfoSeq_var infoSeq = IdlGetUnionInfo(desc -> type);
	    for(j = 0 ; j < infoSeq -> length() ; j++)
		infoSeq[j].name = fixName(infoSeq[j].name);

	    CORBA_String_var discStr = CORBA_string_dup("discriminator");
	    CORBA_String_var defStr = CORBA_string_dup("_default");
	    for(j = 0 ; j < infoSeq -> length() ; j++)
	    {
		if(strcmp(infoSeq[j].name, discStr) == 0)
		    discStr = CORBA_string_dup("_discriminator");

		if(strcmp(infoSeq[j].name, defStr) == 0)
		    defStr = CORBA_string_dup("__default");
	    }

	    comment(desc -> id, out);
	    docComment(desc -> id, out);

	    out.sep();
	    out << "\nfinal public class " << name;
	    out.start();

	    out << "\njava.lang.Object _ob_v_;";
	    out << "\nboolean _ob_i_;";
	    out << '\n' << intDisc << " _ob_d_;";

	    out.sep();
	    out << "\nstatic boolean\n_OB_check(" << intDisc << " d0, "
		<< intDisc << " d1)";
	    out.start();
	    bool needSwitch = false;
	    for(j = 0 ; j < infoSeq -> length() ; j++)
	    {
		IdlUnionMemberInfo& info = infoSeq[j];
		if(info.nLabels.length() + info.pLabels.length() > 1 ||
		   info.isDefault)
		{
		    needSwitch = true;
		    break;
		}
	    }
	    if(needSwitch)
	    {
		out << '\n' << intDisc << " d[] = new " << intDisc << "[2];";
		out << "\nd[0] = d0;";
		out << "\nd[1] = d1;";
		out.sep();
		out << "\nfor(int i = 0 ; i < 2 ; i++)";
		out.start();
		out << "\nswitch(d[i])";
		out.start();
		for(j = 0 ; j < infoSeq -> length() ; j++)
		{
		    IdlUnionMemberInfo& info = infoSeq[j];
		    IdlStringSeq_var labels =
			getUnionLabelSeq(package, origDiscType, info);
		    
		    if(j > 0)
			out.sep();
		    
		    out.dec();
		    
		    if(CORBA_is_nil(info.type))
		    {
			assert(info.isDefault);
			out << "\ndefault:";
		    }
		    else
		    {
			if(info.isDefault)
			    out << "\ndefault:";
			else
			{
			    for(k = 0 ; k < labels -> length() ; k++)
				out << "\ncase " << labels[k] << ':';
			}
		    }
		    
		    out.inc();
		    
		    if(labels -> length() > 1 || info.isDefault)
			out << "\nd[i] = " << labels[0] << ';';
		    
		    out << "\nbreak;";
		}
		out.end();
		out.end();
		out.sep();
		out << "\nreturn d[0] == d[1];";
	    }
	    else
	    {
		out << "\nreturn d0 == d1;";
	    }
	    out.end();

	    out.sep();
	    out << "\npublic\n" << name << "()";
	    out.start();
	    out << "\n_ob_i_ = false;";
	    out.end();

	    out.sep();
	    out << "\npublic " << disc << '\n' << discStr << "()";
	    out.start();
	    out << "\nif(!_ob_i_)";
	    out.inc();
	    out << "\nthrow new org.omg.CORBA.BAD_OPERATION();";
	    out.dec();
	    out.sep();
	    if(origDiscType -> kind() == CORBA_tk_enum)
		out << "\nreturn " << disc << ".from_int(_ob_d_);";
	    else if(origDiscType -> kind() == CORBA_tk_boolean)
		out << "\nreturn _ob_d_ == 0 ? false : true;";
	    else
		out << "\nreturn _ob_d_;";
	    out.end();

	    for(j = 0 ; j < infoSeq -> length() ; j++)
	    {
		IdlUnionMemberInfo& info = infoSeq[j];
		IdlStringSeq_var labels =
		    getUnionLabelSeq(package, origDiscType, info);

		if(CORBA_is_nil(info.type))
		{
		    out.sep();
		    out << "\npublic void\n" << defStr << "()";
		    out.start();
		    out << "\n_ob_i_ = true;";
		    out << "\n_ob_d_ = " << labels[0] << ';';
		    out << "\n_ob_v_ = null;";
		    out.end();

		    if(info.nLabels.length() + info.pLabels.length() > 1 ||
		       info.isDefault)
		    {
			out.sep();
			out << "\npublic void\n" << defStr << '('
			    << disc << " _ob_d)";
			out.start();
			if(origDiscType -> kind() == CORBA_tk_enum)
			    out << "\nif(!_OB_check(_ob_d.value(), "
				<< labels[0] << "))";
			else if(origDiscType -> kind() == CORBA_tk_boolean)
			    out << "\nif(!_OB_check(_ob_d ? 1 : 0, "
				<< labels[0] << "))";
			else
			    out << "\nif(!_OB_check(_ob_d, "
				<< labels[0] << "))";
			out.inc();
			out << "\nthrow new org.omg.CORBA.BAD_OPERATION();";
			out.dec();
			out.sep();
			out << "\n_ob_i_ = true;";
			if(origDiscType -> kind() == CORBA_tk_enum)
			    out << "\n_ob_d_ = _ob_d.value();";
			else if(origDiscType -> kind() == CORBA_tk_boolean)
			    out << "\n_ob_d_ = _ob_d ? 1 : 0;";
			else
			    out << "\n_ob_d_ = _ob_d;";
			out << "\n_ob_v_ = null;";
			out.end();
		    }
		}
		else
		{
		    CORBA_String_var norm = getTypeString(package, info.type);
		    CORBA_TypeCode_var origMemberType =
			OBGetOrigType(info.type);

		    CORBA_String_var holder =
			getUnionMemberHolder(origMemberType);

		    out.sep();
		    out << "\npublic " << norm << '\n' << info.name << "()";
		    out.start();
		    out << "\nif(!_ob_i_)";
		    out.inc();
		    out << "\nthrow new org.omg.CORBA.BAD_OPERATION();";
		    out.dec();
		    out.sep();
		    out << "\nif(!_OB_check(_ob_d_, " << labels[0] << "))";
		    out.inc();
		    out << "\nthrow new org.omg.CORBA.BAD_OPERATION();";
		    out.dec();
		    out.sep();
		    if(strlen(holder) > 0)
			out << "\nreturn ((" << holder << ")_ob_v_).value;";
		    else
			out << "\nreturn (" << norm << ")_ob_v_;";
		    out.end();

		    out.sep();
		    out << "\npublic void\n" << info.name << '(' << norm
			<< " _ob_v)";
		    out.start();
		    out << "\n_ob_i_ = true;";
		    out << "\n_ob_d_ = " << labels[0] << ';';
		    if(strlen(holder) > 0)
			out << "\n_ob_v_ = new " << holder << "(_ob_v);";
		    else
			out << "\n_ob_v_ = _ob_v;";
		    out.end();

		    if(info.nLabels.length() + info.pLabels.length() > 1 ||
		       info.isDefault)
		    {
			out.sep();
			out << "\npublic void\n" << info.name << '('
			    << disc << " _ob_d, " << norm << " _ob_v)";
			out.start();
			if(origDiscType -> kind() == CORBA_tk_enum)
			    out << "\nif(!_OB_check(_ob_d.value(), "
				<< labels[0] << "))";
			else if(origDiscType -> kind() == CORBA_tk_boolean)
			    out << "\nif(!_OB_check(_ob_d ? 1 : 0, "
				<< labels[0] << "))";
			else
			    out << "\nif(!_OB_check(_ob_d, "
				<< labels[0] << "))";
			out.inc();
			out << "\nthrow new org.omg.CORBA.BAD_OPERATION();";
			out.dec();
			out.sep();
			out << "\n_ob_i_ = true;";
			if(origDiscType -> kind() == CORBA_tk_enum)
			    out << "\n_ob_d_ = _ob_d.value();";
			else if(origDiscType -> kind() == CORBA_tk_boolean)
			    out << "\n_ob_d_ = _ob_d ? 1 : 0;";
			else
			    out << "\n_ob_d_ = _ob_d;";
			if(strlen(holder) > 0)
			    out << "\n_ob_v_ = new " << holder << "(_ob_v);";
			else
			    out << "\n_ob_v_ = _ob_v;";
			out.end();
		    }
		}
	    }

	    if(clone_)
		writeClone(seq[i].kind, name, package, desc -> type, out);

	    out.end();

	    //
	    // Write the holder class
	    //
	    CORBA_String_var holder = name;
	    holder += "Holder";
	    PrettyPrint outHolder(fileNameSeq_, prog_, holder, package,
				  outDir_);
	    if(!outHolder.good())
		return 1;
	    
	    comment(desc -> id, outHolder);
	    
	    writeHolder(name, name, outHolder);

	    //
	    // Write the helper class
	    //
//	    if(!local_)
	    {
		CORBA_String_var helper = name;
		helper += "Helper";
		PrettyPrint outHelper(fileNameSeq_, prog_, helper, package,
				      outDir_);
		if(!outHelper.good())
		    return 1;

		comment(desc -> id, outHelper);

		writeHelper(package, desc -> type, outHelper);
	    }

	    break;
	}

	case CORBA_dk_Attribute:
	{
	    //
	    // Attribute
	    //
	    CORBA_AttributeDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    if(!check(desc -> id))
		continue;

	    CORBA_Identifier_var name = fixName(desc -> name);
	    CORBA_String_var package = getPackage(desc -> id);

	    comment(desc -> id, out);
	    docComment(desc -> id, out);

	    CORBA_String_var norm = getTypeString(package, desc -> type);

	    out.sep();
	    out << "\npublic " << norm << '\n' << name << "();";
	    if(desc -> mode == CORBA_ATTR_NORMAL)
	    {
		out.sep();
		out << "\npublic void\n" << name << "(" << norm << " value);";
	    }

	    break;
	}

	case CORBA_dk_Operation:
	{
	    //
	    // Operation
	    //
	    CORBA_OperationDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    if(!check(desc -> id))
		continue;

	    CORBA_Identifier_var name = fixName(desc -> name);
	    CORBA_String_var package = getPackage(desc -> id);

	    comment(desc -> id, out);
	    docComment(desc -> id, out);

	    CORBA_String_var norm = getTypeString(package, desc -> result);

	    out.sep();
	    out << "\npublic " << norm << '\n' << name << "(";
	    
	    unsigned int indent = out.getIndent();
	    out.setIndent(out.getPos());

	    for(j = 0 ; j < desc -> parameters.length() ; j++)
	    {
		GetType gt;
		switch(desc -> parameters[j].mode)
		{
		case CORBA_PARAM_IN:
		    gt = GetTypeNormal;
		    break;

		case CORBA_PARAM_INOUT:
		case CORBA_PARAM_OUT:
		    gt = GetTypeHolder;
		    break;
		}

		CORBA_String_var str =
		    getTypeString(package, desc -> parameters[j].type, gt);

		if(j > 0)
		    out << ",\n";

		CORBA_String_var argName = fixName(desc -> parameters[j].name);

		out << str << ' ' << argName;
	    }

	    if(desc -> contexts.length() > 0)
	    {
		if(desc -> parameters.length() > 0)
		    out << ",\n";
		
		out << "org.omg.CORBA.Context ctx";
	    }

	    out.setIndent(indent);

	    out << ')';

	    if(desc -> exceptions.length())
	    {
		out.inc();
		out << "\nthrows ";

		unsigned int indent = out.getIndent();
		out.setIndent(out.getPos());

		for(j = 0 ; j < desc -> exceptions.length() ; j++)
		{
		    if(j)
			out << ",\n";

		    CORBA_String_var str =
			getTypeString(package, desc -> exceptions[j].type);
    
		    out << str;
		}

		out.setIndent(indent);
		out.dec();
	    }

	    out << ';';

	    break;
	}

	default:
	    break;
	}
    }

    return status;
}

// ----------------------------------------------------------------------
// Generate Java skeleton code, general part
// ----------------------------------------------------------------------

int
IdlJavaGenerator::genJavaSkel(CORBA_Container_ptr container,
			      IdlPrettyPrint& out)
{
    //
    // Get container contents descriptions
    //
    CORBA_Container::DescriptionSeq_var seq =
	container -> describe_contents(CORBA_dk_all, true, -1);

    CORBA_ULong i, j;

    int status = 0;
    for(i = 0 ; status == 0 && i < seq -> length() ; i++)
    {
	//
	// Get container
	//
	CORBA_Container_var cont =
	    CORBA_Container::_narrow(seq[i].contained_object);

	switch(seq[i].kind)
	{
	case CORBA_dk_Module:
	{
	    //
	    // Module
	    //
	    CORBA_ModuleDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    // Don't add this here!!!
	    // if(!check(desc -> id))
	    //     continue;

	    assert(!CORBA_is_nil(cont));
	    status = genJavaSkel(cont, out);

	    break;
	}

	case CORBA_dk_Interface:
	{
	    //
	    // Interface
	    //
	    CORBA_InterfaceDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    if(!check(desc -> id))
		continue;

	    CORBA_Identifier_var name = fixName(desc -> name);
	    CORBA_String_var package = getPackage(desc -> id);

	    CORBA_String_var skel = CORBA_string_dup("_");
	    skel += name;
	    skel += "ImplBase";

	    unsigned int indent;

	    PrettyPrint out(fileNameSeq_, prog_, skel, package, outDir_);
	    if(!out.good())
		return 1;
	    
	    comment(desc -> id, out);

	    out.sep();
	    out << "\npublic abstract class " << skel << ' ';
	    indent = out.getIndent();
	    out.setIndent(out.getPos());
	    out << "extends org.omg.CORBA.DynamicImplementation";
	    out << "\nimplements " << name;
	    out.setIndent(indent);

	    out.start();

	    assert(!CORBA_is_nil(cont));
	    status = genJavaSkelPrivate(cont, desc -> id, out);

	    CORBA_InterfaceDef_var interf =
		CORBA_InterfaceDef::_narrow(seq[i].contained_object);
	    assert(!CORBA_is_nil(interf));

	    CORBA_InterfaceDefSeq allBaseInterfaces;
	    IdlGetAllBaseInterfaces(interf, allBaseInterfaces);

	    out << "\nstatic final String[] _ob_ids_ =";
	    out.start();
	    out << "\n\"" << desc -> id << "\",";
	    for(j = 0 ; j < allBaseInterfaces.length() ; j++)
	    {
		CORBA_RepositoryId_var id =
		    allBaseInterfaces[j] -> id();
		out << "\n\"" << id << '"';
		if(j + 1 < allBaseInterfaces.length())
		    out << ',';
	    }
	    out.end();
	    out << ';';

	    out.sep();
	    out << "\npublic String[]\n_ids()";
	    out.start();
	    out << "\nreturn _ob_ids_;";
	    out.end();

	    out.sep();
	    out << "\nfinal public void\ninvoke(org.omg.CORBA.ServerRequest "
		<< "_ob_req)";
	    out.start();

            //
            // Method name table for operations
            //
            CORBA_ContainedSeq_var operations =
		interf -> contents(CORBA_dk_Operation, false);
	    CORBA_ContainedSeq_var attributes =
		interf -> contents(CORBA_dk_Attribute, false);
            IdlStringSeq_var names = IdlGetMethodNames(attributes, operations);
            
            if(names -> length() > 0)
            {
                //
                // Emit the operation table
                //
                out << "\nString _ob_op = _ob_req.op_name();";
                out << "\nfinal String[] _ob_names =";
                out.start();
                for(j = 0; j < names -> length(); j++)
                {
                    if(j != 0)
                        out << ",";
                    out << "\n\"" << names[j] << "\"";
                }
                out.end();
		out << ';';

                //
                // Binary search the table
                //
                out.sep();
                out << "\nint _ob_left = 0;";
                out << "\nint _ob_right = _ob_names.length;";
                out << "\nint _ob_index = -1;";
		
                out.sep();
                out << "\nwhile(_ob_left < _ob_right)";
                out.start();
                out << "\nint _ob_m = (_ob_left + _ob_right) / 2;";
                out << "\nint _ob_res = _ob_names[_ob_m].compareTo(_ob_op);";
                out << "\nif(_ob_res == 0)";
                out.start();
                out << "\n_ob_index = _ob_m;";
                out << "\nbreak;";
                out.end();
                out << "\nelse if(_ob_res > 0)";
                out.inc();
                out << "\n_ob_right = _ob_m;";
                out.dec();
                out << "\nelse";
                out.inc();
                out << "\n_ob_left = _ob_m + 1;";
                out.dec();
                out.end();

                //
                // Emit the giant switch statement
                //
                out.sep();
                out << "\nswitch(_ob_index)";
                out.start();
		out.dec();

                for(j = 0 ; j < names -> length(); j++)
                {
		    if(j > 0)
			out.sep();
                    out << "\ncase " << j << ": // " << names[j];
		    out.inc();
                    int len = strlen(names[j]);
		    out << "\n_OB";
                    if(!(len > 5 && (strncmp(names[j], "_get_", 5) == 0 ||
				     strncmp(names[j], "_set_", 5) == 0)))
			out << "_op_";
		    out << names[j] << "(_ob_req);";
		    out << "\nreturn;";
		    out.dec();
                }

		out.inc();
                out.end();
	    }
            
            if(names -> length() > 0)
		out.sep();

	    out << "\nthrow new org.omg.CORBA.BAD_OPERATION();";

	    out.end();

	    out.end();

	    break;
	}

	default:
	    break;
	}
    }

    return status;
}

// ----------------------------------------------------------------------
// Generate Java skeleton code, private part
// ----------------------------------------------------------------------

int
IdlJavaGenerator::genJavaSkelPrivate(CORBA_Container_ptr container,
				     const char* package,
				     IdlPrettyPrint& out)
{
    //
    // Get container contents descriptions
    //
    CORBA_Container::DescriptionSeq_var seq =
	container -> describe_contents(CORBA_dk_all, false, -1);

    CORBA_ULong i, j;

    int status = 0;
    for(i = 0 ; status == 0 && i < seq -> length() ; i++)
    {
	switch(seq[i].kind)
	{
	case CORBA_dk_Attribute:
	{
	    //
	    // Attribute
	    //
	    CORBA_AttributeDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    // Don't add this here!!!
	    // if(!check(desc -> id))
	    //     continue;

	    CORBA_Identifier_var name = fixName(desc -> name);
	    // Don't use this here - we are still in the package in
	    // which the interface is in
	    // CORBA_String_var package = getPackage(desc -> id);

	    comment(desc -> id, out);
	    docComment(desc -> id, out);

	    //
	    // Don't use name here instead of desc -> name. We need
	    // the name "unfixed".
	    //
	    out.sep();
	    out << "\nfinal private void\n_OB_get_" << desc -> name
		<< "(org.omg.CORBA.ServerRequest _ob_req)";
	    out.start();
	    out << "\norg.omg.CORBA.NVList _ob_list = _orb().create_list(0);";
	    out << "\n_ob_req.params(_ob_list);";
	    CORBA_String_var result = getTypeString(package, desc -> type);
	    out.sep();
	    out << '\n' << result << " _ob_r = " << name << "();";
	    out.sep();
	    out << "\norg.omg.CORBA.Any _ob_ra = _orb().create_any();";
	    out << '\n';
	    writeInsertExtract(package, desc -> type, "_ob_ra", false, out);
	    out << "_ob_r);";
	    out << "\n_ob_req.result(_ob_ra);";
	    out.end();

	    if(desc -> mode == CORBA_ATTR_NORMAL)
	    {
		//
		// Don't use name here instead of desc -> name. We need
		// the name "unfixed".
		//
		out.sep();
		out << "\nfinal private void\n_OB_set_" << desc -> name
		    << "(org.omg.CORBA.ServerRequest _ob_req)";
		out.start();
		out << "\norg.omg.CORBA.NVList _ob_list = "
		    << "_orb().create_list(0);";
		out << "\norg.omg.CORBA.Any _ob_aa = _orb().create_any();";
		out << "\n_ob_aa.type(";
		writeTypeCode("_orb()", package, desc -> type, out);
		out << ");";
		out << "\n_ob_list.add_value(\"\", _ob_aa, "
		    << "org.omg.CORBA.ARG_IN.value);";
		out << "\n_ob_req.params(_ob_list);";
		CORBA_String_var result = getTypeString(package, desc -> type);
		out.sep();
		out << '\n' << result << " _ob_a = ";
		writeInsertExtract(package, desc -> type, "_ob_aa", true, out);
		out << ';';
		out.sep();
		out << '\n' << name << "(_ob_a);";
		out.end();
	    }

	    break;
	}

	case CORBA_dk_Operation:
	{
	    //
	    // Operation
	    //
	    CORBA_OperationDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    // Don't add this here!!!
	    // if(!check(desc -> id))
	    //     continue;

	    CORBA_Identifier_var name = fixName(desc -> name);
	    // Don't use this here - we are still in the package in
	    // which the interface is in
	    // CORBA_String_var package = getPackage(desc -> id);

	    comment(desc -> id, out);
	    docComment(desc -> id, out);

	    //
	    // Don't use name here instead of desc -> name. We need
	    // the name "unfixed".
	    //
	    out.sep();
	    out << "\nfinal private void\n_OB_op_" << desc -> name
		<< "(org.omg.CORBA.ServerRequest _ob_req)";
	    out.start();
	    out << "\norg.omg.CORBA.NVList _ob_list = _orb().create_list(0);";

	    bool haveOutOrInOut = false;
	    
	    for(j = 0 ; j < desc -> parameters.length() ; j++)
	    {
		out << "\norg.omg.CORBA.Any _ob_aa" << j
		    << " = _orb().create_any();";
		
		switch(desc -> parameters[j].mode)
		{
		case CORBA_PARAM_IN:
		    out << "\n_ob_aa" << j << ".type(";
		    writeTypeCode("_orb()", package,
				  desc -> parameters[j].type, out);
		    out << ");";
		    out << "\n_ob_list.add_value(\"\", _ob_aa" << j
			<< ", org.omg.CORBA.ARG_IN.value);";
		    break;
		    
		case CORBA_PARAM_INOUT:
		    out << "\n_ob_aa" << j << ".type(";
		    writeTypeCode("_orb()", package,
				  desc -> parameters[j].type, out);
		    out << ");";
		    out << "\n_ob_list.add_value(\"\", _ob_aa" << j
			<< ", org.omg.CORBA.ARG_INOUT.value);";
		    haveOutOrInOut = true;
		    break;
		    
		case CORBA_PARAM_OUT:
		    out << "\n_ob_list.add_value(\"\", _ob_aa" << j
			<< ", org.omg.CORBA.ARG_OUT.value);";
		    haveOutOrInOut = true;
		    break;
		}
	    }
	    
	    out << "\n_ob_req.params(_ob_list);";
	    
	    if(desc -> contexts.length() > 0)
	    {
		out << "\norg.omg.CORBA.Context _ob_ctx = _ob_req.ctx();";
	    }
	    
	    for(j = 0 ; j < desc -> parameters.length() ; j++)
	    {
		if(j == 0)
		    out.sep();
		
		switch(desc -> parameters[j].mode)
		{
		case CORBA_PARAM_IN:
		{
		    CORBA_String_var str =
			getTypeString(package, desc -> parameters[j].type);
		    
		    out << '\n' << str << " _ob_a" << j << " = ";
		    CORBA_String_var any = CORBA_string_dup("_ob_aa");
		    any += j;
		    writeInsertExtract(package, desc ->parameters[j].type, any,
				       true, out);
		    out << ';';
		    break;
		}
		
		case CORBA_PARAM_INOUT:
		{
		    CORBA_String_var str =
			getTypeString(package, desc -> parameters[j].type,
				      GetTypeHolder);
		    out << '\n' << str << " _ob_ah" << j << " = new " << str
			<< "();";
		    out << "\n_ob_ah" << j << ".value = ";
		    CORBA_String_var any = CORBA_string_dup("_ob_aa");
		    any += j;
		    writeInsertExtract(package, desc ->parameters[j].type, any,
				       true, out);
		    out << ';';
		    break;
		}
		
		case CORBA_PARAM_OUT:
		{
		    CORBA_String_var str =
			getTypeString(package, desc -> parameters[j].type,
				      GetTypeHolder);
		    out << '\n' << str << " _ob_ah" << j << " = new " << str
			<< "();";
		    break;
		}
		}
	    }
	    
	    CORBA_TypeCode_var origRet = OBGetOrigType(desc -> result);
	    
	    if(origRet -> kind() != CORBA_tk_void)
	    {
		CORBA_String_var result =
		    getTypeString(package, desc -> result);
		out.sep();
		if(desc -> exceptions.length() > 0)
		{
		    out << "\ntry";
		    out.start();
		}
		out << '\n' << result << " _ob_r = ";
	    }
	    else
	    {
		out.sep();
		if(desc -> exceptions.length() > 0)
		{
		    out << "\ntry";
		    out.start();
		}
		out << '\n';
	    }
	    
	    out << name << '(';
	    
	    for(j = 0 ; j < desc -> parameters.length() ; j++)
	    {
		if(j > 0)
		    out << ", ";
		
		switch(desc -> parameters[j].mode)
		{
		case CORBA_PARAM_IN:
		    out << "_ob_a" << j;
		    break;
		    
		case CORBA_PARAM_INOUT:
		case CORBA_PARAM_OUT:
		    out << "_ob_ah" << j;
		    break;
		}
	    }
	    
	    if(desc -> contexts.length() > 0)
	    {
		if(desc -> parameters.length() > 0)
		    out << ", ";
		
		out << "_ob_ctx";
	    }
	    
	    out << ");";
	    
	    if(haveOutOrInOut)
		out.sep();
	    
	    for(j = 0 ; j < desc -> parameters.length() ; j++)
	    {
		switch(desc -> parameters[j].mode)
		{
		case CORBA_PARAM_IN:
		    break;
		    
		case CORBA_PARAM_INOUT:
		case CORBA_PARAM_OUT:
		{
		    out << '\n';
		    CORBA_String_var any = CORBA_string_dup("_ob_aa");
		    any += j;
		    writeInsertExtract(package, desc -> parameters[j].type,
				       any, false, out);
		    out << "_ob_ah" << j << ".value);";
		    break;
		}
		}
	    }
	    
	    if(origRet -> kind() != CORBA_tk_void)
	    {
		out.sep();
		out << "\norg.omg.CORBA.Any _ob_ra = _orb().create_any();";
		out << '\n';
		writeInsertExtract(package, desc -> result,
				   "_ob_ra", false, out);
		out << "_ob_r);";
		out << "\n_ob_req.result(_ob_ra);";
	    }
	    
	    if(desc -> exceptions.length() > 0)
	    {
		out.end();
		
		for(j = 0; j < desc -> exceptions.length(); j++)
		{
		    CORBA_String_var str =
			getTypeString(package, desc -> exceptions[j].type);
		    
		    CORBA_String_var strHelper =
			getTypeString(package, desc -> exceptions[j].type,
				      GetTypeHelper);
		    
		    out << "\ncatch(" << str << " _ob_ex)";
		    out.start();
		    out << "\norg.omg.CORBA.Any _ob_exa = "
			<< "_orb().create_any();";
		    out << '\n' << strHelper
			<< ".insert(_ob_exa, _ob_ex);";
		    out << "\n_ob_req.except(_ob_exa);";
		    out.end();
		}
	    }

	    out.end();

	    break;
	}

	default:
	    break;
	}
    }

    return status;
}

// ----------------------------------------------------------------------
// Generate Java TIE classes
// ----------------------------------------------------------------------

int
IdlJavaGenerator::genJavaTie(CORBA_Container_ptr container,
			     IdlPrettyPrint& out)
{
    //
    // Get container contents descriptions
    //
    CORBA_Container::DescriptionSeq_var seq =
	container -> describe_contents(CORBA_dk_all, true, -1);

    CORBA_ULong i, j, k;

    int status = 0;
    for(i = 0 ; status == 0 && i < seq -> length() ; i++)
    {
	//
	// Get container
	//
	CORBA_Container_var cont =
	    CORBA_Container::_narrow(seq[i].contained_object);

	switch(seq[i].kind)
	{
	case CORBA_dk_Module:
	{
	    //
	    // Module
	    //
	    CORBA_ModuleDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    // Don't add this here!!!
	    // if(!check(desc -> id))
	    //     continue;

	    assert(!CORBA_is_nil(cont));
	    status = genJavaTie(cont, out);

	    break;
	}

	case CORBA_dk_Interface:
	{
	    //
	    // Interface
	    //
	    CORBA_InterfaceDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    if(!check(desc -> id))
		continue;

	    CORBA_Identifier_var name = fixName(desc -> name);
	    CORBA_String_var package = getPackage(desc -> id);

	    unsigned int indent;

	    //
	    // Operations Interface for the interface
	    //
	    CORBA_String_var op = CORBA_string_dup(name);
	    op += "Operations";
	    PrettyPrint outOp(fileNameSeq_, prog_, op, package, outDir_);
	    if(!outOp.good())
		return 1;

	    comment(desc -> id, outOp);

	    outOp.sep();
	    outOp << "\npublic interface " << op;

	    if(desc -> base_interfaces.length() > 0)
	    {
		outOp << " extends ";
		indent = outOp.getIndent();
		outOp.setIndent(outOp.getPos());


		for(j = 0 ; j < desc -> base_interfaces.length() ; j++)
		{
		    const char* id = desc -> base_interfaces[j];
		    CORBA_ScopedName_var absolute = getAbsolute(id);
		    removePackage(package, absolute.inout());

		    if(j > 0)
			outOp << ",\n";

		    outOp << absolute << "Operations";
		}

		outOp.setIndent(indent);
	    }

	    outOp.start();
	    status = genJavaTie(cont, outOp);
	    outOp.end();

	    //
	    // TIE class for the interface
	    //
	    CORBA_String_var tie = CORBA_string_dup("_");
	    tie += name;
	    tie += "ImplBase_tie";
	    PrettyPrint outTie(fileNameSeq_, prog_, tie, package, outDir_);
	    if(!outTie.good())
		return 1;

	    comment(desc -> id, outTie);

	    outTie.sep();
	    outTie << "\npublic class " << tie << " extends _" << name
		   << "ImplBase";

	    outTie.start();

	    outTie << "\nprivate " << op << " delegate_;";
	    outTie.sep();

	    outTie << "\npublic" << '\n' << tie << "(" << op << " op)";
	    outTie.start();
	    outTie << "\ndelegate_ = op;";
	    outTie.end();

	    outTie.sep();

	    outTie << "\npublic " << op << '\n' << "_delegate()";
	    outTie.start();
	    outTie << "\nreturn delegate_;";
	    outTie.end();

	    outTie.sep();

	    outTie << "\npublic void" << '\n' << "_delegate(" << op
		   << " op)";
	    outTie.start();
	    outTie << "\ndelegate_ = op;";
	    outTie.end();

	    CORBA_InterfaceDef_var interf =
		CORBA_InterfaceDef::_narrow(seq[i].contained_object);
	    assert(!CORBA_is_nil(interf));

	    CORBA_ContainedSeq_var attributes =
		interf -> contents(CORBA_dk_Attribute, false);

	    CORBA_ContainedSeq_var operations =
		interf -> contents(CORBA_dk_Operation, false);

	    for(j = 0 ; j < attributes -> length() ; j++)
	    {
		CORBA_Contained::Description_var contDesc =
		    attributes[j] -> describe();
		CORBA_AttributeDescription* atDesc;
		CORBA_Boolean b = (contDesc -> value) >>= atDesc;
		assert(b);

		CORBA_Identifier_var atName = fixName(atDesc -> name);

		comment(atDesc -> id, outTie);

		CORBA_String_var result =
		    getTypeString(package, atDesc -> type);
		outTie.sep();
		outTie << "\npublic " << result << '\n' << atName << "()";
		outTie.start();
		outTie << "\nreturn delegate_." << atName << "();";
		outTie.end();

		if(atDesc -> mode == CORBA_ATTR_NORMAL)
		{
		    outTie.sep();
		    outTie << "\npublic void\n" << atName << '('
			<< result << " _ob_a)";
		    outTie.start();
		    outTie << "\ndelegate_." << atName << "(_ob_a);";
		    outTie.end();
		}
	    }

	    for(j = 0 ; j < operations -> length() ; j++)
	    {
		CORBA_Contained::Description_var contDesc =
		    operations[j] -> describe();
		CORBA_OperationDescription* opDesc;
		CORBA_Boolean b = (contDesc -> value) >>= opDesc;
		assert(b);

		CORBA_Identifier_var opName = fixName(opDesc -> name);

		comment(opDesc -> id, outTie);

		CORBA_TypeCode_var origRet =
		    OBGetOrigType(opDesc -> result);

		CORBA_String_var result = getTypeString(package, origRet);
		outTie.sep();
		outTie << "\npublic " << result << '\n' << opName << "(";

		unsigned int indent = outTie.getIndent();
		outTie.setIndent(outTie.getPos());

		for(k = 0 ; k < opDesc -> parameters.length() ; k++)
		{
		    if(k > 0)
			outTie << ",\n";

		    switch(opDesc -> parameters[k].mode)
		    {
		    case CORBA_PARAM_IN:
		    {
			CORBA_String_var str =
			    getTypeString(package,
					  opDesc -> parameters[k].type);
			outTie << str << " _ob_a" << k;
			break;
		    }

		    case CORBA_PARAM_INOUT:
		    case CORBA_PARAM_OUT:
		    {
			CORBA_String_var str =
			    getTypeString(package,
					  opDesc -> parameters[k].type,
					  GetTypeHolder);
			outTie << str << " _ob_ah" << k;
			break;
		    }
		    }
		}

		if(opDesc -> contexts.length() > 0)
		{
		    if(opDesc -> parameters.length() > 0)
			outTie << ",\n";

		    outTie << "org.omg.CORBA.Context _ob_ctx";
		}

		outTie.setIndent(indent);

		outTie << ')';

		if(opDesc -> exceptions.length())
		{
		    outTie.inc();
		    outTie << "\nthrows ";

		    unsigned int indent = outTie.getIndent();
		    outTie.setIndent(outTie.getPos());

		    for(k = 0 ; k < opDesc -> exceptions.length() ; k++)
		    {
			if(k)
			    outTie << ",\n";

			CORBA_String_var str =
			    getTypeString(package,
					  opDesc -> exceptions[k].type);

			outTie << str;
		    }

		    outTie.setIndent(indent);
		    outTie.dec();
		}

		outTie.start();

		outTie << '\n';

		if(origRet -> kind() != CORBA_tk_void)
		    outTie << "return ";

		outTie << "delegate_." << opName << "(";
		indent = outTie.getIndent();
		outTie.setIndent(outTie.getPos());

		for(k = 0 ; k < opDesc -> parameters.length() ; k++)
		{
		    if(k > 0)
			outTie << ",\n";

		    switch(opDesc -> parameters[k].mode)
		    {
		    case CORBA_PARAM_IN:
		    {
			outTie << "_ob_a" << k;
			break;
		    }

		    case CORBA_PARAM_INOUT:
		    case CORBA_PARAM_OUT:
		    {
			outTie << "_ob_ah" << k;
			break;
		    }
		    }
		}

		if(opDesc -> contexts.length() > 0)
		{
		    if(opDesc -> parameters.length() > 0)
			outTie << ",\n";

		    outTie << "_ob_ctx";
		}

		outTie << ");";
		outTie.setIndent(indent);
		outTie.end();
	    }

	    outTie.end();

	    break;
	}

	case CORBA_dk_Attribute:
	{
	    //
	    // Attribute
	    //
	    CORBA_AttributeDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    if(!check(desc -> id))
		continue;

	    CORBA_Identifier_var name = fixName(desc -> name);
	    CORBA_String_var package = getPackage(desc -> id);

	    comment(desc -> id, out);
	    docComment(desc -> id, out);

	    CORBA_String_var norm = getTypeString(package, desc -> type);

	    out.sep();
	    out << "\npublic " << norm << '\n' << name << "();";
	    if(desc -> mode == CORBA_ATTR_NORMAL)
	    {
		out.sep();
		out << "\npublic void\n" << name << "(" << norm << " value);";
	    }

	    break;
	}

	case CORBA_dk_Operation:
	{
	    //
	    // Operation
	    //
	    CORBA_OperationDescription* desc;
	    CORBA_Boolean b = seq[i].value >>= desc;
	    assert(b);

	    if(!check(desc -> id))
		continue;

	    CORBA_Identifier_var name = fixName(desc -> name);
	    CORBA_String_var package = getPackage(desc -> id);

	    comment(desc -> id, out);
	    docComment(desc -> id, out);

	    CORBA_String_var norm = getTypeString(package, desc -> result);

	    out.sep();
	    out << "\npublic " << norm << '\n' << name << "(";

	    unsigned int indent = out.getIndent();
	    out.setIndent(out.getPos());

	    for(j = 0 ; j < desc -> parameters.length() ; j++)
	    {
		GetType gt;
		switch(desc -> parameters[j].mode)
		{
		case CORBA_PARAM_IN:
		    gt = GetTypeNormal;
		    break;

		case CORBA_PARAM_INOUT:
		case CORBA_PARAM_OUT:
		    gt = GetTypeHolder;
		    break;
		}

		CORBA_String_var str =
		    getTypeString(package, desc -> parameters[j].type, gt);

		if(j > 0)
		    out << ",\n";

		CORBA_String_var argName = fixName(desc -> parameters[j].name);

		out << str << ' ' << argName;
	    }

	    if(desc -> contexts.length() > 0)
	    {
		if(desc -> parameters.length() > 0)
		    out << ",\n";

		out << "org.omg.CORBA.Context ctx";
	    }

	    out.setIndent(indent);

	    out << ')';

	    if(desc -> exceptions.length())
	    {
		out.inc();
		out << "\nthrows ";

		unsigned int indent = out.getIndent();
		out.setIndent(out.getPos());

		for(j = 0 ; j < desc -> exceptions.length() ; j++)
		{
		    if(j)
			out << ",\n";

		    CORBA_String_var str =
			getTypeString(package, desc -> exceptions[j].type);

		    out << str;
		}

		out.setIndent(indent);
		out.dec();
	    }

	    out << ';';

	    break;
	}

	default:
	    break;
	}
    }

    return status;
}

// ----------------------------------------------------------------------
// Write constants
// ----------------------------------------------------------------------

void
IdlJavaGenerator::writeConstant(const CORBA_Any& value, IdlPrettyPrint& out)
{
    CORBA_TypeCode_var tc = value.type();
    tc = OBGetOrigType(tc);

    switch(tc -> kind())
    {
    case CORBA_tk_short:
    {
	CORBA_Short v;
	CORBA_Boolean b = value >>= v;
	assert(b);
	out << "(short)(" << v << "L)";
	break;
    }

    case CORBA_tk_ushort:
    {
	CORBA_UShort v;
	CORBA_Boolean b = value >>= v;
	assert(b);
	out << "(short)(" << v << "L)";
	break;
    }

    case CORBA_tk_long:
    {
	CORBA_Long v;
	CORBA_Boolean b = value >>= v;
	assert(b);
	out << "(int)(" << v << "L)";
	break;
    }

    case CORBA_tk_ulong:
    {
	CORBA_ULong v;
	CORBA_Boolean b = value >>= v;
	assert(b);
	out << "(int)(" << v << "L)";
	break;
    }

    case CORBA_tk_float:
    {
	CORBA_Float v;
	CORBA_Boolean b = value >>= v;
	assert(b);
	out << "(float)(" << v << "D)";
	break;
    }

    case CORBA_tk_double:
    {
	CORBA_Double v;
	CORBA_Boolean b = value >>= v;
	assert(b);
	out << "(double)(" << v << "D)";
	break;
    }

    case CORBA_tk_string:
    {
	char* v;
	CORBA_ULong l = tc -> length();
	CORBA_Any::to_string to(v, l);
	CORBA_Boolean b = value >>= to;
	assert(b);
	CORBA_String_var s = CORBA_string_dup(v);
	addEscapes(s.inout(), true);
	out << s;
	break;
    }

    case CORBA_tk_char:
    {
	CORBA_Char v;
	CORBA_Boolean b = value >>= CORBA_Any::to_char(v);
	assert(b);
	CORBA_String_var s;
	if(v == '\0')
	    s = CORBA_string_dup("\\0");
	else
	{
	    s = CORBA_string_alloc(1);
	    s[0] = v;
	    s[1] = '\0';
	    addEscapes(s.inout(), false);
	}
	out << "'" << s << "'";
	break;
    }

    case CORBA_tk_boolean:
    {
	CORBA_Boolean v;
	CORBA_Boolean b = value >>= CORBA_Any::to_boolean(v);
	assert(b);
	out << (v == CORBA_TRUE ? "true" : "false");
	break;
    }

    default:
	assert(false);
	break;
    }
}

// ----------------------------------------------------------------------
// Write the holder class
// ----------------------------------------------------------------------

void
IdlJavaGenerator::writeHolder(const char* norm, const char* name,
			      IdlPrettyPrint& out)
{
    out.sep();
    out << "\nfinal public class " << name << "Holder"
	<< " implements org.omg.CORBA.portable.Streamable";
    out.start();

    out << "\npublic " << norm << " value;";

    out.sep();
    out << "\npublic\n" << name << "Holder" << "()";
    out.start();
    out.end();

    out.sep();
    out << "\npublic\n" << name << "Holder" << "(" << norm << " initial)";
    out.start();
    out << "\nvalue = initial;";
    out.end();

    out.sep();
    out << "\npublic void\n_read(org.omg.CORBA.portable.InputStream in)";
    out.start();
    if(local_)
	out << "\nthrow new org.omg.CORBA.MARSHAL();";
    else
	out << "\nvalue = " << name << "Helper.read(in);";
    out.end();

    out.sep();
    out << "\npublic void\n_write(org.omg.CORBA.portable.OutputStream out)";
    out.start();
    if(local_)
	out << "\nthrow new org.omg.CORBA.MARSHAL();";
    else
	out << "\n" << name << "Helper.write(out, value);";
    out.end();

    out.sep();
    out << "\npublic org.omg.CORBA.TypeCode\n_type()";
    out.start();
    if(local_)
	out << "\nthrow new org.omg.CORBA.BAD_OPERATION();";
    else
	out << "\nreturn " << name << "Helper.type();";
    out.end();

    out.end();
}

// ----------------------------------------------------------------------
// Write the helper class
// ----------------------------------------------------------------------

void
IdlJavaGenerator::writeHelper(const char* package, CORBA_TypeCode_ptr tc,
			      IdlPrettyPrint& out)
{
    CORBA_RepositoryId_var id = tc -> id();
    CORBA_Identifier_var name = fixName(tc -> name());
    CORBA_String_var norm = getTypeString(package, tc);

    CORBA_TypeCode_var origType = OBGetOrigType(tc);

    out.sep();
    out << "\nfinal public class " << name << "Helper";
    out.start();

    //
    // Insertion to any
    //
    out << "\npublic static void\ninsert(org.omg.CORBA.Any any, " << norm
	<< " val)";
    out.start();
    if(local_)
    {
	out << "\nthrow new org.omg.CORBA.MARSHAL();";
    }
    else
    {
	switch(origType -> kind())
	{
	case CORBA_tk_null:
	case CORBA_tk_void:
	    assert(false);
	    break;
	    
	case CORBA_tk_short:
	    out << "\nany.insert_short(val);";
	    break;
	    
	case CORBA_tk_long:
	    out << "\nany.insert_long(val);";
	    break;
	    
	case CORBA_tk_ushort:
	    out << "\nany.insert_ushort(val);";
	    break;
	    
	case CORBA_tk_ulong:
	    out << "\nany.insert_ulong(val);";
	    break;
	    
	case CORBA_tk_float:
	    out << "\nany.insert_float(val);";
	    break;
	    
	case CORBA_tk_double:
	    out << "\nany.insert_double(val);";
	    break;
	    
	case CORBA_tk_boolean:
	    out << "\nany.insert_boolean(val);";
	    break;
	    
	case CORBA_tk_char:
	    out << "\nany.insert_char(val);";
	    break;
	    
	case CORBA_tk_octet:
	    out << "\nany.insert_octet(val);";
	    break;
	    
	case CORBA_tk_string:
	    out << "\nany.insert_string(val);";
	    break;
	    
	case CORBA_tk_any:
	    out << "\nany.insert_any(val);";
	    break;
	    
	case CORBA_tk_TypeCode:
	    out << "\nany.insert_TypeCode(val);";
	    break;
	    
	case CORBA_tk_Principal:
	    out << "\nany.insert_Principal(val);";
	    break;
	    
	case CORBA_tk_objref:
	    if(strcmp(origType -> id(), "IDL:omg.org/CORBA/Object:1.0") == 0)
	    {
		out << "\nany.insert_Object(val);";
		break;
	    }
	    // No break here!

	case CORBA_tk_struct:
	case CORBA_tk_union:
	case CORBA_tk_except:
	case CORBA_tk_enum:
	case CORBA_tk_sequence:
	case CORBA_tk_array:
	    out << "\norg.omg.CORBA.portable.OutputStream out = "
		<< "any.create_output_stream();";
	    out << "\nwrite(out, val);";
	    out << "\nany.read_value(out.create_input_stream(), type());";
	    break;
	    
	case CORBA_tk_alias:
	    assert(false);
	    break;
	}
    }
    out.end();

    //
    // Extraction from any
    //
    out.sep();
    out << "\npublic static " << norm << "\nextract(org.omg.CORBA.Any any)";
    out.start();
    if(local_)
    {
	out << "\nthrow new org.omg.CORBA.MARSHAL();";
    }
    else
    {
	switch(origType -> kind())
	{
	case CORBA_tk_null:
	case CORBA_tk_void:
	    assert(false);
	    break;

	case CORBA_tk_short:
	    out << "\nreturn any.extract_short();";
	    break;

	case CORBA_tk_long:
	    out << "\nreturn any.extract_long();";
	    break;

	case CORBA_tk_ushort:
	    out << "\nreturn any.extract_ushort();";
	    break;

	case CORBA_tk_ulong:
	    out << "\nreturn any.extract_ulong();";
	    break;

	case CORBA_tk_float:
	    out << "\nreturn any.extract_float();";
	    break;

	case CORBA_tk_double:
	    out << "\nreturn any.extract_double();";
	    break;

	case CORBA_tk_boolean:
	    out << "\nreturn any.extract_boolean();";
	    break;

	case CORBA_tk_char:
	    out << "\nreturn any.extract_char();";
	    break;

	case CORBA_tk_octet:
	    out << "\nreturn any.extract_octet();";
	    break;

	case CORBA_tk_string:
	    out << "\nreturn any.extract_string();";
	    break;

	case CORBA_tk_any:
	    out << "\nreturn any.extract_any();";
	    break;

	case CORBA_tk_TypeCode:
	    out << "\nreturn any.extract_TypeCode();";
	    break;

	case CORBA_tk_Principal:
	    out << "\nreturn any.extract_Principal();";
	    break;

	case CORBA_tk_objref:
	    if(strcmp(origType -> id(), "IDL:omg.org/CORBA/Object:1.0") == 0)
	    {
		out << "\nreturn any.extract_Object();";
		break;
	    }
	    // No break here!

	case CORBA_tk_struct:
	case CORBA_tk_union:
	case CORBA_tk_except:
	case CORBA_tk_enum:
	case CORBA_tk_sequence:
	case CORBA_tk_array:
	    out << "\nif(any.type().equal(type()))";
	    out.inc();
	    out << "\nreturn read(any.create_input_stream());";
	    out.dec();
	    out << "\nelse";
	    out.inc();
	    out << "\nthrow new org.omg.CORBA.BAD_OPERATION();";
	    out.dec();
	    break;

	case CORBA_tk_alias:
	    assert(false);
	    break;
	}
    }
    out.end();

    //
    // Return the TypeCode
    //
    if(!local_)
    {
	out.sep();
	out << "\nprivate static org.omg.CORBA.TypeCode typeCode_;";
    }
    out.sep();
    out << "\npublic static org.omg.CORBA.TypeCode\ntype()";
    out.start();
    if(local_)
    {
	out << "\nthrow new org.omg.CORBA.BAD_OPERATION();";
    }
    else
    {
	out << "\nif(typeCode_ == null)";
	out.start();
	out << "\norg.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();";
	switch(tc -> kind()) // Don't use origType here!
	{
	case CORBA_tk_null:
	case CORBA_tk_void:
	    assert(false);
	    break;

	case CORBA_tk_short:
	case CORBA_tk_long:
	case CORBA_tk_ushort:
	case CORBA_tk_ulong:
	case CORBA_tk_float:
	case CORBA_tk_double:
	case CORBA_tk_boolean:
	case CORBA_tk_char:
	case CORBA_tk_octet:
	case CORBA_tk_string:
	case CORBA_tk_any:
	case CORBA_tk_TypeCode:
	case CORBA_tk_Principal:
	case CORBA_tk_sequence:
	case CORBA_tk_array:
	    out << "\ntypeCode_ = ";
	    writeTypeCode("orb", package, tc, out);
	    out << ';';
	    break;

	case CORBA_tk_objref:
	{
	    CORBA_RepositoryId_var id = tc -> id();
	    out << "\ntypeCode_ = orb.create_interface_tc(id(), \""
		<< tc -> name() << "\");";
	    break;
	}

	case CORBA_tk_struct:
	case CORBA_tk_except:
	{
	    out << "\norg.omg.CORBA.StructMember[] members = "
		<< "new org.omg.CORBA.StructMember["
		<< tc -> member_count() << "];";

	    for(CORBA_ULong i = 0 ; i < tc -> member_count() ; i++)
	    {
		CORBA_TypeCode_var memberType = tc -> member_type(i);
		const char* memberName = tc -> member_name(i);

		out.sep();
		out << "\nmembers[" << i << "] = "
		    << "new org.omg.CORBA.StructMember();";
		out << "\nmembers[" << i << "].name = \"" << memberName
		    << "\";";
		out << "\nmembers[" << i << "].type = ";
		writeTypeCode("orb", package, memberType, out);
		out << ';';
	    }

	    out.sep();
	    if(tc -> kind() == CORBA_tk_struct)
		out << "\ntypeCode_ = orb.create_struct_tc(id(), \"";
	    else
		out << "\ntypeCode_ = orb.create_exception_tc(id(), \"";

	    out << tc -> name() << "\", members);";

	    break;
	}

	case CORBA_tk_union:
	{
	    out << "\norg.omg.CORBA.UnionMember[] members = "
		<< "new org.omg.CORBA.UnionMember["
		<< tc -> member_count() << "];";

	    for(CORBA_ULong i = 0 ; i < tc -> member_count() ; i++)
	    {
		CORBA_TypeCode_var memberType = tc -> member_type(i);
		const char* memberName = tc -> member_name(i);
		CORBA_Any_var memberLabel = tc -> member_label(i); 

		out.sep();
		out << "\nmembers[" << i
		    << "] = new org.omg.CORBA.UnionMember();";
		out << "\nmembers[" << i << "].name = \"" << memberName
		    << "\";";
		out << "\nmembers[" << i << "].type = ";
		writeTypeCode("orb", package, memberType, out);
		out << ';';
		out << "\nmembers[" << i << "].label = orb.create_any();";

		CORBA_TypeCode_var origMemberLabelType = memberLabel -> type();
		origMemberLabelType = OBGetOrigType(origMemberLabelType);
		switch(origMemberLabelType -> kind())
		{
		case CORBA_tk_short:
		    out << "\nmembers[" << i << "].label."
			<< "insert_short(";
		    writeConstant(memberLabel, out);
		    out << ");";
		    break;

		case CORBA_tk_ushort:
		    out << "\nmembers[" << i << "].label."
			<< "insert_ushort(";
		    writeConstant(memberLabel, out);
		    out << ");";
		    break;

		case CORBA_tk_long:
		    out << "\nmembers[" << i << "].label."
			<< "insert_long(";
		    writeConstant(memberLabel, out);
		    out << ");";
		    break;

		case CORBA_tk_ulong:
		    out << "\nmembers[" << i << "].label."
			<< "insert_ulong(";
		    writeConstant(memberLabel, out);
		    out << ");";
		    break;

		case CORBA_tk_char:
		    out << "\nmembers[" << i << "].label."
			<< "insert_char(";
		    writeConstant(memberLabel, out);
		    out << ");";
		    break;

		case CORBA_tk_boolean:
		    out << "\nmembers[" << i << "].label."
			<< "insert_boolean(";
		    writeConstant(memberLabel, out);
		    out << ");";
		    break;

		case CORBA_tk_enum:
		{
		    CORBA_String_var memberLabelNorm =
			getTypeString(package, origMemberLabelType);
		    CORBA_String_var memberLabelHelper =
			getTypeString(package, origMemberLabelType,
				      GetTypeHelper);
		    CORBA_ULong val = *(CORBA_ULong*)(memberLabel -> value());
		    out << '\n' << memberLabelHelper << ".insert(members[" << i
			<< "].label, " << memberLabelNorm << ".from_int("
			<< val << "));";
		    break;
		}

		case CORBA_tk_octet:
		{
#ifndef NDEBUG
		    CORBA_Octet octet;
		    assert(memberLabel >>= CORBA_Any::to_octet(octet));
		    assert(octet == 0);
#endif
		    out << "\nmembers[" << i
			<< "].label.insert_octet((byte)0);";
		    break;
		}

		default:
		    assert(false);
		    break;
		}
	    }

	    out.sep();
	    CORBA_TypeCode_var discType = tc -> discriminator_type();
	    out << "\norg.omg.CORBA.TypeCode discType = ";
	    writeTypeCode("orb", package, discType, out);
	    out << ';';

	    out << "\ntypeCode_ = orb.create_union_tc(id(), \"" << tc -> name()
		<< "\", discType, members);";

	    break;
	}

	case CORBA_tk_enum:
	{
	    out << "\nString[] members = new String["
		<< tc -> member_count() << "];";

	    for(CORBA_ULong i = 0 ; i < tc -> member_count() ; i++)
	    {
		const char* memberName = tc -> member_name(i);
		out << "\nmembers[" << i << "] = \"" << memberName << "\";";
	    }

	    out << "\ntypeCode_ = orb.create_enum_tc(id(), \"" << tc -> name()
		<< "\", members);";

	    break;
	}

	case CORBA_tk_alias:
	{
	    CORBA_TypeCode_var contentType = tc -> content_type();
	    out << "\ntypeCode_ = orb.create_alias_tc(id(), \"" << tc -> name()
		<< "\", ";
	    writeTypeCode("orb", package, contentType, out);
	    out << ");";
	    break;
	}
	}
	out.end();

	out.sep();
	out << "\nreturn typeCode_;";
    }
    out.end();

    //
    // Return the repository ID
    //
    out.sep();
    out << "\npublic static String\nid()";
    out.start();
    out << "\nreturn \"" << id << "\";";
    out.end();
    
    //
    // Read from input stream
    //
    out.sep();
    out << "\npublic static " << norm
	<< "\nread(org.omg.CORBA.portable.InputStream in)";
    out.start();
    if(local_)
    {
	out << "\nthrow new org.omg.CORBA.MARSHAL();";
    }
    else
    {
	switch(tc -> kind())
	{
	case CORBA_tk_null:
	case CORBA_tk_void:
	    assert(false);
	    break;

	case CORBA_tk_short:
	case CORBA_tk_long:
	case CORBA_tk_ushort:
	case CORBA_tk_ulong:
	case CORBA_tk_float:
	case CORBA_tk_double:
	case CORBA_tk_boolean:
	case CORBA_tk_char:
	case CORBA_tk_octet:
	case CORBA_tk_string:
	case CORBA_tk_any:
	case CORBA_tk_TypeCode:
	case CORBA_tk_Principal:
	case CORBA_tk_array:
	case CORBA_tk_sequence:
	{
	    out << '\n' << norm << " val;";
	    CORBA_ULong iter = 0;
	    writeReaderWriter(package, tc, "val", iter, true, out);
	    out << "\nreturn val;";
	    break;
	}

	case CORBA_tk_objref:
	{
	    out << "\norg.omg.CORBA.Object obj = in.read_Object();";
	    out << "\nif(obj == null)";
	    out.inc();
	    out << "\nreturn null;";
	    out.dec();
	    out.sep();
	    out << "\ntry";
	    out.start();
	    out << "\nreturn (" << norm << ")obj;";
	    out.end();
	    out << "\ncatch(ClassCastException ex)";
	    out.start();
	    out.end();
	    out.sep();
	    out << "\norg.omg.CORBA.portable.ObjectImpl impl;";
	    out << "\nimpl = (org.omg.CORBA.portable.ObjectImpl)obj;";
	    out << "\nStubFor" << norm << " stub = new StubFor" << norm
		<< "();";
	    out << "\nstub._set_delegate(impl._get_delegate());";
	    out << "\nreturn stub;";
	    break;
	}

	case CORBA_tk_struct:
	case CORBA_tk_except:
	{
	    if(tc -> kind() == CORBA_tk_except)
	    {
		out << "\nif(!id().equals(in.read_string()))";
		out.inc();
		out << "\nthrow new org.omg.CORBA.MARSHAL();";
		out.dec();
		out.sep();
	    }

	    out << '\n' << norm << " val = new " << name << "();";
	    CORBA_ULong iter = 0;
	    for(CORBA_ULong i = 0 ; i < tc -> member_count() ; i++)
	    {
		CORBA_TypeCode_var memberType = tc -> member_type(i);
		CORBA_Identifier_var memberName = tc -> member_name(i);
		memberName = fixName(memberName);
		CORBA_String_var fullName = CORBA_string_dup("val.");
		fullName += memberName;
		writeReaderWriter(package, memberType, fullName, iter, true,
				  out);
	    }
	    out << "\nreturn val;";
	    break;
	}

	case CORBA_tk_union:
	{
	    CORBA_ULong i, j;

	    CORBA_TypeCode_var discType = tc -> discriminator_type();
	    CORBA_TypeCode_var origDiscType = OBGetOrigType(discType);
	    CORBA_String_var disc = getTypeString(package, discType);
	    CORBA_String_var intDisc;
	    if(origDiscType -> kind() == CORBA_tk_enum ||
	       origDiscType -> kind() == CORBA_tk_boolean)
		intDisc = CORBA_string_dup("int");
	    else
		intDisc = disc;

	    IdlUnionMemberInfoSeq_var infoSeq = IdlGetUnionInfo(tc);
	    for(i = 0 ; i < infoSeq -> length() ; i++)
		infoSeq[i].name = fixName(infoSeq[i].name);

	    CORBA_String_var defStr = CORBA_string_dup("_default");
	    for(j = 0 ; j < infoSeq -> length() ; j++)
		if(strcmp(infoSeq[j].name, defStr) == 0)
		    defStr = CORBA_string_dup("__default");

	    CORBA_ULong iter = 0;

	    out << '\n' << norm << " val = new " << name << "();";
	    out << '\n' << disc << " d;";
	    writeReaderWriter(package, discType, "d", iter, true, out);

	    out.sep();
	    if(origDiscType -> kind() == CORBA_tk_enum)
		out << "\nswitch(d.value())";
	    else if(origDiscType -> kind() == CORBA_tk_boolean)
		out << "\nswitch(d ? 1 : 0)";
	    else
		out << "\nswitch(d)";
	    out.start();
	    for(i = 0 ; i < infoSeq -> length() ; i++)
	    {
		IdlUnionMemberInfo& info = infoSeq[i];
		IdlStringSeq_var labels =
		    getUnionLabelSeq(package, origDiscType, info);

		if(i > 0)
		    out.sep();

		out.dec();

		if(CORBA_is_nil(info.type))
		{
		    assert(info.isDefault);
		    out << "\ndefault:";
		    out.inc();
		    if(info.nLabels.length() + info.pLabels.length() > 1 ||
		       info.isDefault)
			out << "\nval." << defStr << "(d);";
		    else
			out << "\nval." << defStr << "();";
		    out << "\nbreak;";
		    out.dec();
		}
		else
		{
		    if(info.isDefault)
			out << "\ndefault:";
		    else
		    {
			for(j = 0 ; j < labels -> length() ; j++)
			    out << "\ncase " << labels[j] << ':';
		    }

		    out.start();
		    CORBA_String_var norm = getTypeString(package, info.type);
		    out << '\n' << norm << " v;";
		    writeReaderWriter(package, info.type, "v", iter, true,
				      out);
		    if(info.nLabels.length() + info.pLabels.length() > 1 ||
		       info.isDefault)
			out << "\nval." << info.name << "(d, v);";
		    else
			out << "\nval." << info.name << "(v);";
		    out << "\nbreak;";
		    out.end();
		}

		out.inc();

	    }
	    out.end();

	    out << "\nreturn val;";

	    break;
	}

	case CORBA_tk_enum:
	    out << '\n' << norm << " val;";
	    out << "\nval = " << name << ".from_int(in.read_ulong());";
	    out << "\nreturn val;";
	    break;

	case CORBA_tk_alias:
	{
	    CORBA_TypeCode_var contentType = tc -> content_type();
	    out << '\n' << norm << " val;";
	    CORBA_ULong iter = 0;
	    writeReaderWriter(package, contentType, "val", iter, true, out);
	    out << "\nreturn val;";
	    break;
	}
	}
    }
    out.end();

    //
    // Write to output stream
    //
    out.sep();
    out << "\npublic static void\nwrite("
	<< "org.omg.CORBA.portable.OutputStream out, "
	<< norm << " val)";
    out.start();
    if(local_)
    {
	out << "\nthrow new org.omg.CORBA.MARSHAL();";
    }
    else
    {
	switch(tc -> kind())
	{
	case CORBA_tk_null:
	case CORBA_tk_void:
	    assert(false);
	    break;

	case CORBA_tk_short:
	case CORBA_tk_long:
	case CORBA_tk_ushort:
	case CORBA_tk_ulong:
	case CORBA_tk_float:
	case CORBA_tk_double:
	case CORBA_tk_boolean:
	case CORBA_tk_char:
	case CORBA_tk_octet:
	case CORBA_tk_string:
	case CORBA_tk_any:
	case CORBA_tk_TypeCode:
	case CORBA_tk_Principal:
	case CORBA_tk_array:
	case CORBA_tk_sequence:
	{
	    CORBA_ULong iter = 0;
	    writeReaderWriter(package, tc, "val", iter, false, out);
	    break;
	}

	case CORBA_tk_objref:
	    out << "\nout.write_Object(val);";
	    break;

	case CORBA_tk_struct:
	case CORBA_tk_except:
	{
	    if(tc -> kind() == CORBA_tk_except)
		out << "\nout.write_string(id());";

	    CORBA_ULong iter = 0;
	    for(CORBA_ULong i = 0 ; i < tc -> member_count() ; i++)
	    {
		CORBA_TypeCode_var memberType = tc -> member_type(i);
		CORBA_Identifier_var memberName = tc -> member_name(i);
		memberName = fixName(memberName);
		CORBA_String_var fullName = CORBA_string_dup("val.");
		fullName += memberName;
		writeReaderWriter(package, memberType, fullName,
				  iter, false, out);
	    }
	    break;
	}

	case CORBA_tk_union:
	{
	    CORBA_ULong i, j;

	    CORBA_TypeCode_var discType = tc -> discriminator_type();
	    CORBA_TypeCode_var origDiscType = OBGetOrigType(discType);
	    CORBA_String_var disc = getTypeString(package, discType);
	    CORBA_String_var intDisc;
	    if(origDiscType -> kind() == CORBA_tk_enum ||
	       origDiscType -> kind() == CORBA_tk_boolean)
		intDisc = CORBA_string_dup("int");
	    else
		intDisc = disc;

	    IdlUnionMemberInfoSeq_var infoSeq = IdlGetUnionInfo(tc);
	    for(i = 0 ; i < infoSeq -> length() ; i++)
		infoSeq[i].name = fixName(infoSeq[i].name);

	    CORBA_String_var discStr = CORBA_string_dup("discriminator");
	    for(i = 0 ; i < infoSeq -> length() ; i++)
		if(strcmp(infoSeq[i].name, discStr) == 0)
		    discStr = CORBA_string_dup("_discriminator");

	    CORBA_ULong iter = 0;

	    out << '\n' << disc << " d = val." << discStr << "();";
	    writeReaderWriter(package, discType, "d", iter, false, out);

	    out.sep();
	    if(origDiscType -> kind() == CORBA_tk_enum)
		out << "\nswitch(d.value())";
	    else if(origDiscType -> kind() == CORBA_tk_boolean)
		out << "\nswitch(d ? 1 : 0)";
	    else
		out << "\nswitch(d)";
	    out.start();
	    for(i = 0 ; i < infoSeq -> length() ; i++)
	    {
		IdlUnionMemberInfo& info = infoSeq[i];
		IdlStringSeq_var labels =
		    getUnionLabelSeq(package, origDiscType, info);

		if(i > 0)
		    out.sep();

		out.dec();

		if(CORBA_is_nil(info.type))
		{
		    assert(info.isDefault);
		    out << "\ndefault:";
		    out.inc();
		    out << "\nbreak;";
		    out.dec();
		}
		else
		{
		    if(info.isDefault)
			out << "\ndefault:";
		    else
		    {
			for(j = 0 ; j < labels -> length() ; j++)
			    out << "\ncase " << labels[j] << ':';
		    }

		    out.start();
		    CORBA_String_var norm = getTypeString(package, info.type);
		    out << '\n' << norm << " v = val." << info.name << "();";
		    writeReaderWriter(package, info.type, "v", iter, false,
				      out);
		    out << "\nbreak;";
		    out.end();
		}

		out.inc();

	    }
	    out.end();

	    break;
	}

	case CORBA_tk_enum:
	    out << "\nout.write_ulong(val.value());";
	    break;

	case CORBA_tk_alias:
	{
	    CORBA_TypeCode_var contentType = tc -> content_type();
	    CORBA_ULong iter = 0;
	    writeReaderWriter(package, contentType, "val", iter, false, out);
	    break;
	}
	}
    }
    out.end();

    //
    // Narrow, only for interfaces
    //
    if(origType -> kind() == CORBA_tk_objref)
    {
	out.sep();
	out << "\npublic static " << norm
	    << "\nnarrow(org.omg.CORBA.Object obj)";
	out.start();
	
	if(strcmp(origType -> id(), "IDL:omg.org/CORBA/Object:1.0") == 0)
	{
	    out << "\nreturn obj;";
	}
	else
	{    
	    out << "\nif(obj != null)";
	    out.start();
	    
	    out << "\ntry";
	    out.start();
	    out << "\nreturn (" << norm << ")obj;";
	    out.end();
	    out << "\ncatch(ClassCastException ex)";
	    out.start();
	    out.end();

	    if(!local_)
	    {
		CORBA_String_var stub =
		    getTypeString(package, tc, GetTypeStub);

		out.sep();
		out << "\nif(obj._is_a(id()))";
		out.start();
		out << "\norg.omg.CORBA.portable.ObjectImpl impl;";
		out << "\nimpl = (org.omg.CORBA.portable.ObjectImpl)obj;";
		out << '\n' << stub << " stub = new " << stub << "();";
		out << "\nstub._set_delegate(impl._get_delegate());";
		out << "\nreturn stub;";
		out.end();
	    }

	    out.end();
	    out.sep();
	    out << "\nreturn null;";
	}
	    
	out.end();
    }

    out.end();
}

// ----------------------------------------------------------------------
// Write TypeCode
// ----------------------------------------------------------------------

void
IdlJavaGenerator::writeTypeCode(const char* orb, const char* package,
				CORBA_TypeCode_ptr tc, IdlPrettyPrint& out)
{
    switch(tc -> kind())
    {
    case CORBA_tk_null:
    case CORBA_tk_void:
	assert(false);
	break;

    case CORBA_tk_short:
	out << orb << ".get_primitive_tc(org.omg.CORBA.TCKind.tk_short)";
	break;

    case CORBA_tk_long:
	out << orb << ".get_primitive_tc(org.omg.CORBA.TCKind.tk_long)";
	break;

    case CORBA_tk_ushort:
	out << orb << ".get_primitive_tc(org.omg.CORBA.TCKind.tk_ushort)";
	break;

    case CORBA_tk_ulong:
	out << orb << ".get_primitive_tc(org.omg.CORBA.TCKind.tk_ulong)";
	break;

    case CORBA_tk_float:
	out << orb << ".get_primitive_tc(org.omg.CORBA.TCKind.tk_float)";
	break;
	
    case CORBA_tk_double:
	out << orb << ".get_primitive_tc(org.omg.CORBA.TCKind.tk_double)";
	break;

    case CORBA_tk_boolean:
	out << orb << ".get_primitive_tc(org.omg.CORBA.TCKind.tk_boolean)";
	break;

    case CORBA_tk_char:
	out << orb << ".get_primitive_tc(org.omg.CORBA.TCKind.tk_char)";
	break;

    case CORBA_tk_octet:
	out << orb << ".get_primitive_tc(org.omg.CORBA.TCKind.tk_octet)";
	break;

    case CORBA_tk_string:
    {
	if(tc -> length() == 0)
	    out << orb << ".get_primitive_tc(org.omg.CORBA.TCKind.tk_string)";
	else
	    out << orb << ".create_string_tc(" << tc -> length() << ")";
	break;
    }

    case CORBA_tk_any:
	out << orb << ".get_primitive_tc(org.omg.CORBA.TCKind.tk_any)";
	break;

    case CORBA_tk_TypeCode:
	out << orb << ".get_primitive_tc(org.omg.CORBA.TCKind.tk_TypeCode)";
	break;

    case CORBA_tk_Principal:
	out << orb << ".get_primitive_tc(org.omg.CORBA.TCKind.tk_Principal)";
	break;

    case CORBA_tk_objref:
    {
	const char* id = tc -> id();
	if(strcmp(id, "IDL:omg.org/CORBA/Object:1.0") == 0)
	{
	    const char* name = tc -> name();
	    out << orb << ".create_interface_tc(\"" << id << "\", \"" << name
		<< "\")";
	}
	else
	{
	    CORBA_String_var helper =
		getTypeString(package, tc, GetTypeHelper);
	    out << helper << ".type()";
	}
	break;
    }

    case CORBA_tk_struct:
    case CORBA_tk_except:
    case CORBA_tk_union:
    case CORBA_tk_enum:
    case CORBA_tk_alias:
    {
	CORBA_String_var helper = getTypeString(package, tc, GetTypeHelper);
	out << helper << ".type()";
	break;
    }

    case CORBA_tk_sequence:
    {
	if(tc -> offset() == 0)
	{
	    CORBA_TypeCode_var contentType = tc -> content_type();

	    out << orb << ".create_sequence_tc(" << tc -> length() << ", ";
	    writeTypeCode(orb, package, contentType, out);
	    out << ')';
	}
	else
	{
	    out << orb << ".create_recursive_sequence_tc("
		<< tc -> length() << ", " << tc -> offset() << ')';
	}

	break;
    }

    case CORBA_tk_array:
    {
	CORBA_TypeCode_var contentType = tc -> content_type();

	out << orb << ".create_array_tc(" << tc -> length() << ", ";
	writeTypeCode(orb, package, contentType, out);
	out << ')';

	break;
    }
    }
}

// ----------------------------------------------------------------------
// Generate code for reading/writing from streams
// ----------------------------------------------------------------------

void
IdlJavaGenerator::writeReaderWriter(const char* package,
				    CORBA_TypeCode_ptr tc,
				    const char* name, CORBA_ULong& iter,
				    bool r, IdlPrettyPrint& out)
{
    switch(tc -> kind())
    {
    case CORBA_tk_null:
    case CORBA_tk_void:
	assert(false);
	break;

    case CORBA_tk_short:
	if(r)
	    out << '\n' << name << " = in.read_short();";
	else
	    out << "\nout.write_short(" << name << ");";
	break;

    case CORBA_tk_long:
	if(r)
	    out << '\n' << name << " = in.read_long();";
	else
	    out << "\nout.write_long(" << name << ");";
	break;

    case CORBA_tk_ushort:
	if(r)
	    out << '\n' << name << " = in.read_ushort();";
	else
	    out << "\nout.write_ushort(" << name << ");";
	break;

    case CORBA_tk_ulong:
	if(r)
	    out << '\n' << name << " = in.read_ulong();";
	else
	    out << "\nout.write_ulong(" << name << ");";
	break;

    case CORBA_tk_float:
	if(r)
	    out << '\n' << name << " = in.read_float();";
	else
	    out << "\nout.write_float(" << name << ");";
	break;

    case CORBA_tk_double:
	if(r)
	    out << '\n' << name << " = in.read_double();";
	else
	    out << "\nout.write_double(" << name << ");";
	break;

    case CORBA_tk_boolean:
	if(r)
	    out << '\n' << name << " = in.read_boolean();";
	else
	    out << "\nout.write_boolean(" << name << ");";
	break;

    case CORBA_tk_char:
	if(r)
	    out << '\n' << name << " = in.read_char();";
	else
	    out << "\nout.write_char(" << name << ");";
	break;

    case CORBA_tk_octet:
	if(r)
	    out << '\n' << name << " = in.read_octet();";
	else
	    out << "\nout.write_octet(" << name << ");";
	break;

    case CORBA_tk_string:
	if(r)
	    out << '\n' << name << " = in.read_string();";
	else
	    out << "\nout.write_string(" << name << ");";
	break;

    case CORBA_tk_any:
	if(r)
	    out << '\n' << name << " = in.read_any();";
	else
	    out << "\nout.write_any(" << name << ");";
	break;

    case CORBA_tk_TypeCode:
	if(r)
	    out << '\n' << name << " = in.read_TypeCode();";
	else
	    out << "\nout.write_TypeCode(" << name << ");";
	break;

    case CORBA_tk_Principal:
	if(r)
	    out << '\n' << name << " = in.read_Principal();";
	else
	    out << "\nout.write_Principal(" << name << ");";
	break;

    case CORBA_tk_objref:
    {
	CORBA_RepositoryId_var id = tc -> id();
	if(strcmp(id, "IDL:omg.org/CORBA/Object:1.0") == 0)
	{
	    if(r)
		out << '\n' << name << " = in.read_Object();";
	    else
		out << "\nout.write_Object(" << name << ");";
	}
	else
	{
	    CORBA_String_var helper =
		getTypeString(package, tc, GetTypeHelper);
	    if(r)
		out << '\n' << name << " = " << helper << ".read(in);";
	    else
		out << '\n' << helper << ".write(out, " << name << ");";
	}
	break;
    }
    
    case CORBA_tk_struct:
    case CORBA_tk_except:
    case CORBA_tk_union:
    case CORBA_tk_enum:
    case CORBA_tk_alias:
    {
	CORBA_String_var helper = getTypeString(package, tc, GetTypeHelper);
	if(r)
	    out << '\n' << name << " = " << helper << ".read(in);";
	else
	    out << '\n' << helper << ".write(out, " << name << ");";
	break;
    }

    case CORBA_tk_sequence:
    case CORBA_tk_array:
    {
	if(r)
	{
	    if(tc -> kind() == CORBA_tk_sequence)
		out << "\nint len" << iter << " = in.read_ulong();";
	    else
		out << "\nint len" << iter << " = " << tc -> length() << ';';

	    CORBA_TypeCode_var t = CORBA_TypeCode::_duplicate(tc);
	    CORBA_String_var s = CORBA_string_dup("");
	    while(t -> kind() == CORBA_tk_sequence ||
		  t -> kind() == CORBA_tk_array)
	    {
		if(strlen(s) > 0)
		    s += "[]";
		else
		{
		    s += "[len";
		    s += iter;
		    s += ']';
		}
		
		t = t -> content_type();
		t = OBGetOrigType(t);
	    }
	    CORBA_String_var n = getTypeString(package, t);
	    out << '\n' << name << " = new " << n << s << ';';
	}
	else
	{
	    out << "\nint len" << iter << " = " << name << ".length;";

	    //
	    // Check array bounds
	    //
	    if(tc -> kind() == CORBA_tk_array)
	    {
		out << "\nif(len" << iter << " != " << tc -> length() << ')';
		out.inc();
		out << "\n throw new org.omg.CORBA.MARSHAL();";
		out.dec();
	    }

	    if(tc -> kind() == CORBA_tk_sequence)
	    {
		//
		// Check bounds for boundes sequences
		//
		if(tc -> length())
		{
		    out << "\nif(len" << iter << " > "
			<< tc -> length() << ')';
		    out.inc();
		    out << "\n throw new org.omg.CORBA.MARSHAL();";
		    out.dec();
		}
		
		out << "\nout.write_ulong(len" << iter << ");";
	    }
	}

	CORBA_TypeCode_var contentType = tc -> content_type();
	switch(contentType -> kind())
	{
	case CORBA_tk_null:
	case CORBA_tk_void:
	    assert(false);
	    break;

	case CORBA_tk_short:
	    if(r)
		out << "\nin.read_short_array(" << name << ", 0, len"
		    << iter << ");";
	    else
		out << "\nout.write_short_array(" << name << ", 0, len"
		    << iter << ");";
	    iter++;
	    break;

	case CORBA_tk_long:
	    if(r)
	    out << "\nin.read_long_array(" << name << ", 0, len"
		<< iter << ");";
	    else
		out << "\nout.write_long_array(" << name << ", 0, len"
		    << iter << ");";
	    iter++;
	    break;

	case CORBA_tk_ushort:
	    if(r)
		out << "\nin.read_ushort_array(" << name << ", 0, len"
		    << iter << ");";
	    else
		out << "\nout.write_ushort_array(" << name << ", 0, len"
		    << iter << ");";
	    iter++;
	    break;

	case CORBA_tk_ulong:
	    if(r)
		out << "\nin.read_ulong_array(" << name << ", 0, len"
		    << iter << ");";
	    else
		out << "\nout.write_ulong_array(" << name << ", 0, len"
		    << iter << ");";
	    iter++;
	    break;

	case CORBA_tk_float:
	    if(r)
		out << "\nin.read_float_array(" << name << ", 0, len"
		    << iter << ");";
	    else
		out << "\nout.write_float_array(" << name << ", 0, len"
		    << iter << ");";
	    iter++;
	    break;

	case CORBA_tk_double:
	    if(r)
		out << "\nin.read_double_array(" << name << ", 0, len"
		    << iter << ");";
	    else
		out << "\nout.write_double_array(" << name << ", 0, len"
		    << iter << ");";
	    iter++;
	    break;

	case CORBA_tk_boolean:
	    if(r)
		out << "\nin.read_boolean_array(" << name << ", 0, len"
		    << iter << ");";
	    else
		out << "\nout.write_boolean_array(" << name << ", 0, len"
		    << iter << ");";
	    iter++;
	    break;

	case CORBA_tk_char:
	    if(r)
		out << "\nin.read_char_array(" << name << ", 0, len"
		    << iter << ");";
	    else
		out << "\nout.write_char_array(" << name << ", 0, len"
		    << iter << ");";
	    iter++;
	    break;

	case CORBA_tk_octet:
	    if(r)
		out << "\nin.read_octet_array(" << name << ", 0, len"
		    << iter << ");";
	    else
		out << "\nout.write_octet_array(" << name << ", 0, len"
		    << iter << ");";
	    iter++;
	    break;

	case CORBA_tk_string:
	{
	    out << "\nfor(int i" << iter << " = 0 ; i" << iter << " < len"
		<< iter << " ; i" << iter << "++)";
	    out.inc();
	    if(r)
		out << '\n' << name << "[i" << iter
		    << "] = in.read_string();";
	    else
		out << "\nout.write_string(" << name << "[i" << iter << "]);";
	    out.dec();
	    iter++;
	    break;
	}

	case CORBA_tk_any:
	{
	    out << "\nfor(int i" << iter << " = 0 ; i" << iter << " < len"
		<< iter << " ; i" << iter << "++)";
	    out.inc();
	    if(r)
		out << '\n' << name << "[i" << iter << "] = in.read_any();";
	    else
		out << "\nout.write_any(" << name << "[i" << iter << "]);";
	    out.dec();
	    iter++;
	    break;
	}

	case CORBA_tk_TypeCode:
	{
	    out << "\nfor(int i" << iter << " = 0 ; i" << iter << " < len"
		<< iter << " ; i" << iter << "++)";
	    out.inc();
	    if(r)
		out << '\n' << name << "[i" << iter
		    << "] = in.read_TypeCode();";
	    else
		out << "\nout.write_TypeCode(" << name
		    << "[i" << iter << "]);";
	    out.dec();
	    iter++;
	    break;
	}

	case CORBA_tk_Principal:
	{
	    out << "\nfor(int i" << iter << " = 0 ; i" << iter << " < len"
		<< iter << " ; i" << iter << "++)";
	    out.inc();
	    if(r)
		out << '\n' << name << "[i" << iter
		    << "] = in.read_Principal();";
	    else
		out << "\nout.write_Principal(" << name
		    << "[i" << iter << "]);";
	    out.dec();
	    iter++;
	    break;
	}

	case CORBA_tk_objref:
	{
	    CORBA_RepositoryId_var id = contentType -> id();
	    if(strcmp(id, "IDL:omg.org/CORBA/Object:1.0") == 0)	
	    {
		out << "\nfor(int i" << iter << " = 0 ; i" << iter << " < len"
		    << iter << " ; i" << iter << "++)";
		out.inc();
		if(r)
		    out << '\n' << name << "[i" << iter
			<< "] = in.read_Object();";
		else
		    out << "\nout.write_Object(" << name
			<< "[i" << iter << "]);";
		out.dec();
		iter++;
	    }
	    else
	    {
		out << "\nfor(int i" << iter << " = 0 ; i" << iter << " < len"
		    << iter << " ; i" << iter << "++)";
		CORBA_String_var helper = getTypeString(package, contentType,
							GetTypeHelper);
		out.inc();
		if(r)
		    out << '\n' << name << "[i" << iter << "] = " << helper
			<< ".read(in);";
		else
		    out << '\n' << helper << ".write(out, " << name
			<< "[i" << iter << "]);";
		out.dec();
		iter++;
	    }
	    break;
	}

	case CORBA_tk_struct:
	case CORBA_tk_except:
	case CORBA_tk_union:
	case CORBA_tk_enum:
	case CORBA_tk_alias:
	{
	    out << "\nfor(int i" << iter << " = 0 ; i" << iter << " < len"
		<< iter << " ; i" << iter << "++)";
	    CORBA_String_var helper = getTypeString(package, contentType,
						    GetTypeHelper);
	    out.inc();
	    if(r)
		out << '\n' << name << "[i" << iter << "] = " << helper
		    << ".read(in);";
	    else
		out << '\n' << helper << ".write(out, " << name
		    << "[i" << iter << "]);";
	    out.dec();
	    iter++;
	    break;
	}

	case CORBA_tk_array:
	case CORBA_tk_sequence:
	{
	    out << "\nfor(int i" << iter << " = 0 ; i" << iter << " < len"
		<< iter << " ; i" << iter << "++)";
	    out.start();
	    CORBA_String_var str = name;
	    str += "[i";
	    str += iter;
	    str += ']';
	    iter++;
	    writeReaderWriter(package, contentType, str, iter, r, out);
	    out.end();
	    
	    break;
	}
	}

	break;
    }
    }
}

// ----------------------------------------------------------------------
// Write any insertion/extraction for stubs/skeletons
// ----------------------------------------------------------------------

void
IdlJavaGenerator::writeInsertExtract(const char* package,
				     CORBA_TypeCode_ptr tc,
				     const char* any, bool ex,
				     IdlPrettyPrint& out)
{
    CORBA_TypeCode_var origType = OBGetOrigType(tc);

    switch(origType -> kind())
    {
    case CORBA_tk_null:
    case CORBA_tk_void:
	assert(false);
	break;

    case CORBA_tk_short:
	if(ex)
	    out << any << ".extract_short()";
	else
	    out << any << ".insert_short(";
	break;

    case CORBA_tk_long:
	if(ex)
	    out << any << ".extract_long()";
	else
	    out << any << ".insert_long(";
	break;

    case CORBA_tk_ushort:
	if(ex)
	    out << any << ".extract_ushort()";
	else
	    out << any << ".insert_ushort(";
	break;

    case CORBA_tk_ulong:
	if(ex)
	    out << any << ".extract_ulong()";
	else
	    out << any << ".insert_ulong(";
	break;

    case CORBA_tk_float:
	if(ex)
	    out << any << ".extract_float()";
	else
	    out << any << ".insert_float(";
	break;

    case CORBA_tk_double:
	if(ex)
	    out << any << ".extract_double()";
	else
	    out << any << ".insert_double(";
	break;

    case CORBA_tk_boolean:
	if(ex)
	    out << any << ".extract_boolean()";
	else
	    out << any << ".insert_boolean(";
	break;

    case CORBA_tk_char:
	if(ex)
	    out << any << ".extract_char()";
	else
	    out << any << ".insert_char(";
	break;

    case CORBA_tk_octet:
	if(ex)
	    out << any << ".extract_octet()";
	else
	    out << any << ".insert_octet(";
	break;

    case CORBA_tk_string:
	if(ex)
	    out << any << ".extract_string()";
	else
	    out << any << ".insert_string(";
	break;

    case CORBA_tk_any:
	if(ex)
	    out << any << ".extract_any()";
	else
	    out << any << ".insert_any(";
	break;

    case CORBA_tk_TypeCode:
	if(ex)
	    out << any << ".extract_TypeCode()";
	else
	    out << any << ".insert_TypeCode(";
	break;

    case CORBA_tk_Principal:
	if(ex)
	    out << any << ".extract_Principal()";
	else
	    out << any << ".insert_Principal(";
	break;

    case CORBA_tk_objref:
	if(strcmp(origType -> id(), "IDL:omg.org/CORBA/Object:1.0") == 0)
	{
	    if(ex)
		out << any << ".extract_Object()";
	    else
		out << any << ".insert_Object(";

	    break;
	}
	// No break here!

    case CORBA_tk_struct:
    case CORBA_tk_union:
    case CORBA_tk_except:
    case CORBA_tk_enum:
    case CORBA_tk_sequence:
    case CORBA_tk_array:
    {	
	CORBA_String_var helper = getTypeString(package, tc, GetTypeHelper);
	
	if(ex)
	    out << helper << ".extract(" << any << ')';
	else
	    out << helper << ".insert(" << any << ", ";

	break;
    }

    case CORBA_tk_alias:
	assert(false);
	break;
    }
}

// ----------------------------------------------------------------------
// Write clone() method
// ----------------------------------------------------------------------

void
IdlJavaGenerator::writeClone(CORBA_DefinitionKind kind, const char *type,
			     const char* package, CORBA_TypeCode_ptr tc,
			     IdlPrettyPrint& out)
{
    out.sep();
    out << "\npublic java.lang.Object";
    out << "\nclone()";
    out.start();

    switch(kind)
    {
    case CORBA_dk_Enum:
	out << "\nreturn new " << type << "(value_);";
	break;

    case CORBA_dk_Struct:
    case CORBA_dk_Exception:
    {
	out << '\n' << type << " _ob_r = new " << type << "();";
	out.sep();

	for(CORBA_ULong i = 0 ; i < tc -> member_count() ; i++)
	{
	    CORBA_TypeCode_var memberType = tc -> member_type(i);
	    CORBA_String_var memberTypeName =
		getTypeString(package, memberType);
	    CORBA_Identifier_var memberName = tc -> member_name(i);
	    memberName = fixName(memberName);
	    CORBA_String_var target = CORBA_string_dup("_ob_r.");
	    target += memberName;

	    //
	    // If member is not primitive, then we need to test if
	    // the member is null
	    //
	    CORBA_TypeCode_var origMemberType = OBGetOrigType(memberType);
	    if(! isPrimitiveMemberType(origMemberType))
	    {
		out << "\nif(" << memberName << " != null)";
		out.start();
		writeMemberClone(target, memberName, package, memberType,
				 memberTypeName, out, 0);
		out.end();
	    }
	    else
		writeMemberClone(target, memberName, package, memberType,
				 memberTypeName, out, 0);
	}

	out.sep();
	out << "\nreturn _ob_r;";
	break;
    }

    case CORBA_dk_Union:
    {
	CORBA_ULong i, j;

	out << '\n' << type << " _ob_r = new " << type << "();";

	out.sep();

	out << "\n_ob_r._ob_i_ = _ob_i_;";
	out << "\n_ob_r._ob_d_ = _ob_d_;";

	out.sep();

	CORBA_TypeCode_var discType = tc -> discriminator_type();
	CORBA_TypeCode_var origDiscType = OBGetOrigType(discType);

	IdlUnionMemberInfoSeq_var infoSeq = IdlGetUnionInfo(tc);
	for(i = 0 ; i < infoSeq -> length() ; i++)
	    infoSeq[i].name = fixName(infoSeq[i].name);

	//
	// Only attempt to clone member if the union has been
	// initialized and the value is not null
	//
	out << "\nif(_ob_i_ && _ob_v_ != null)";
	out.start();

	out << "\nswitch(_ob_d_)";
	out.start();
	for(i = 0 ; i < infoSeq -> length() ; i++)
	{
	    IdlUnionMemberInfo& info = infoSeq[i];
	    IdlStringSeq_var labels =
		getUnionLabelSeq(package, origDiscType, info);

	    //
	    // If the typecode is nil, we don't need to do anything
	    //
	    if(CORBA_is_nil(info.type))
	    {
		assert(info.isDefault);
		continue;
	    }

	    if(i > 0)
		out.sep();

	    out.dec();

	    if(info.isDefault)
		out << "\ndefault:";
	    else
	    {
		for(j = 0 ; j < labels -> length() ; j++)
		    out << "\ncase " << labels[j] << ':';
	    }

	    out.start();

	    CORBA_String_var norm = getTypeString(package, info.type);
	    CORBA_TypeCode_var origMemberType = OBGetOrigType(info.type);

	    CORBA_String_var holder = getUnionMemberHolder(origMemberType);

	    if(strlen(holder) > 0)
	    {
		//out << "\nif(_ob_v_ != null)";
		//out.inc();
		out << "\n_ob_r._ob_v_ = new " << holder << "((("
		    << holder << ")_ob_v_).value);";
		//out.dec();
	    }
	    else
	    {
		switch(origMemberType -> kind())
		{
		case CORBA_tk_string:
		case CORBA_tk_TypeCode:
		case CORBA_tk_Principal:
		case CORBA_tk_objref:
		{
		    writeMemberClone("_ob_r._ob_v_", "_ob_v_", package,
				     origMemberType, norm, out, 0);
		    break;
		}

		case CORBA_tk_any:
		{
		    out << "\norg.omg.CORBA.Any _ob_any_v = "
			<< "(org.omg.CORBA.Any)_ob_v_;";
		    out << "\norg.omg.CORBA.Any _ob_any;";
		    writeMemberClone("_ob_any", "_ob_any_v", package,
				     origMemberType, norm, out, 0);
		    out << "\n_ob_r._ob_v_ = _ob_any;";
		    break;
		}

		case CORBA_tk_struct:
		case CORBA_tk_except:
		case CORBA_tk_union:
		case CORBA_tk_enum:
		{
		    out << "\n_ob_r._ob_v_ = ((" << norm
			<< ")_ob_v_).clone();";
		    break;
		}

		case CORBA_tk_sequence:
		case CORBA_tk_array:
		{
		    out << '\n' << norm << " _ob_arr_v = (" << norm << ")"
			<< "_ob_v_;";
		    out << '\n' << norm << " _ob_arr;";
		    writeMemberClone("_ob_arr", "_ob_arr_v", package,
				     origMemberType, norm, out, 0);
		    out << "\n_ob_r._ob_v_ = _ob_arr;";
		    break;
		}

		default:
		    assert(false);
		    break;
		}
	    }

	    out << "\nbreak;";

	    out.end();  // case stmt
	    out.inc();
	}

	out.end();  // switch stmt
	out.end();  // if stmt

	out.sep();
	out << "\nreturn _ob_r;";
	break;
    }

    default:
	assert(false);
	break;
    }

    out.end();
}

// ----------------------------------------------------------------------
// Write clone() assignment code for struct/union/exception member
// ----------------------------------------------------------------------

void
IdlJavaGenerator::writeMemberClone(const char* target, const char *source,
				   const char* package, CORBA_TypeCode_ptr tc,
				   const char* type, IdlPrettyPrint& out,
				   int iter)
{
    switch(tc -> kind())
    {
    case CORBA_tk_null:
    case CORBA_tk_void:
	assert(false);
	break;

    //
    // All of these can be copied directly (strings, TypeCodes, Principals
    // and Objects are all immutable)
    //
    case CORBA_tk_short:
    case CORBA_tk_long:
    case CORBA_tk_ushort:
    case CORBA_tk_ulong:
    case CORBA_tk_float:
    case CORBA_tk_double:
    case CORBA_tk_boolean:
    case CORBA_tk_char:
    case CORBA_tk_octet:
    case CORBA_tk_string:
    case CORBA_tk_TypeCode:
    case CORBA_tk_Principal:
    case CORBA_tk_objref:
	out << '\n' << target << " = " << source << ";";
	break;

    //
    // Make a deep copy of the any
    //
    case CORBA_tk_any:
    {
	out << '\n' << target
	    << " = org.omg.CORBA.ORB.init().create_any();";
	out << '\n' << target << ".read_value(" << source
	    << ".create_input_stream(), " << source << ".type());";
	break;
    }

    case CORBA_tk_alias:
    {
	CORBA_TypeCode_var contentType = tc -> content_type();
	CORBA_String_var contentTypeName = getTypeString(package, contentType);
	writeMemberClone(target, source, package, contentType, contentTypeName,
			 out, iter);
	break;
    }

    case CORBA_tk_struct:
    case CORBA_tk_except:
    case CORBA_tk_union:
    case CORBA_tk_enum:
    {
	out << '\n' << target << " = (" << type << ")"
	    << source << ".clone();";
	break;
    }

    case CORBA_tk_sequence:
    case CORBA_tk_array:
    {
	CORBA_TypeCode_var contentType = tc -> content_type();
	CORBA_String_var contentTypeName = getTypeString(package, contentType);
	CORBA_TypeCode_var origContentType = OBGetOrigType(contentType);

	//
	// If type is primitive (or immutable), then we can just allocate
	// an array and use System.arraycopy()
	//
	if(isPrimitiveMemberType(origContentType))
	{
	    CORBA_String_var orig = getTypeString(package, origContentType);
	    out << '\n' << target << " = new " << orig << '[' << source
		<< ".length];";
	    out << "\nSystem.arraycopy(" << source << ", 0, " << target
		<< ", 0, " << source << ".length);";
	}
	else
	{
	    CORBA_String_var index = CORBA_string_dup("_ob_i");
	    index += iter;
	    CORBA_String_var targetElement = CORBA_string_dup(target);
	    targetElement += "[";
	    targetElement += index;
	    targetElement += "]";
	    CORBA_String_var sourceElement = CORBA_string_dup(source);
	    sourceElement += "[";
	    sourceElement += index;
	    sourceElement += "]";

	    out << '\n' << target << " = (" << type << ")"
		<< source << ".clone();";

	    out << "\nfor(int " << index << " = 0 ; " << index << " < "
		<< source << ".length ; " << index << "++)";
	    out.start();
	    writeMemberClone(targetElement, sourceElement, package,
			     contentType, contentTypeName, out, iter + 1);
	    out.end();
	}
	break;
    }
    }
}

// ----------------------------------------------------------------------
// Java code generator constructor and destructor
// ----------------------------------------------------------------------

IdlJavaGenerator::IdlJavaGenerator(const char* prog,
				   CORBA_Repository_ptr rep,
				   const IdlCommentSeq& commentSeq,
				   const IdlPrefixPackageSeq& prefixPackageSeq,
				   IdlStringSeq*& fileNameSeq,
				   const char* package,
				   bool autoPackage,
				   bool noComments,
				   bool local,
				   bool clone,
				   const char* outDir)
    : prog_(prog),
      repository_(CORBA_Repository::_duplicate(rep)),
      partial_(false),
      commentSeq_(commentSeq),
      prefixPackageSeq_(prefixPackageSeq),
      fileNameSeq_(fileNameSeq),
      package_(package),
      autoPackage_(autoPackage),
      noComments_(noComments),
      local_(local),
      clone_(clone),
      outDir_(outDir)
{
}

IdlJavaGenerator::IdlJavaGenerator(const char* prog,
				   CORBA_Repository_ptr rep,
				   const CORBA_RepositoryIdSeq& idSeq,
				   const IdlCommentSeq& commentSeq,
				   const IdlPrefixPackageSeq& prefixPackageSeq,
				   IdlStringSeq*& fileNameSeq,
				   const char* package,
				   bool autoPackage,
				   bool noComments,
				   bool local,
				   bool clone,
				   const char* outDir)
    : prog_(prog),
      repository_(CORBA_Repository::_duplicate(rep)),
      partial_(true),
      idSeq_(idSeq),
      commentSeq_(commentSeq),
      prefixPackageSeq_(prefixPackageSeq),
      fileNameSeq_(fileNameSeq),
      package_(package),
      autoPackage_(autoPackage),
      noComments_(noComments),
      local_(local),
      clone_(clone),
      outDir_(outDir)
{
}

// ----------------------------------------------------------------------
// Generate Java code
// ----------------------------------------------------------------------

int
IdlJavaGenerator::gen()
{
    IdlPrettyPrint out(cerr); // Nothing should be printed on this out
    return genJava(repository_, out);
}

int
IdlJavaGenerator::genSkel()
{
    if(local_)
	return 0;

    IdlPrettyPrint out(cerr); // Nothing should be printed on this out
    return genJavaSkel(repository_, out);
}

int
IdlJavaGenerator::genTie()
{
    if(local_)
	return 0;

    IdlPrettyPrint out(cerr); // Nothing should be printed on this out
    return genJavaTie(repository_, out);
}
