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

#ifndef GEN_JAVA_H
#define GEN_JAVA_H

//
// The Java code generator class
//
class IdlJavaGenerator
{
    //
    // Special Java "Pretty-Print" class
    //
    class PrettyPrint : public IdlPrettyPrint
    {
	static const char* header_;
	CORBA_String_var path_;
	ofstream out_;

    public:

	PrettyPrint(IdlStringSeq*&, const char*, const char*, const char*,
		    const char*, unsigned int = 4);
	~PrettyPrint() { out_ << '\n'; }

	const char* path() const { return path_; }
	int good() { return out_.good(); }
    };

    //
    // The program name
    //
    const char* prog_;

    //
    // The repository
    //
    CORBA_Repository_var repository_;

    //
    // If partial_ is set to true, code is only generated for
    // everything that's in idSeq_;
    //
    bool partial_;
    CORBA_RepositoryIdSeq idSeq_;

    //
    // Comments from IDL file
    //
    IdlCommentSeq commentSeq_;

    //
    // Packages for prefixes
    //
    IdlPrefixPackageSeq prefixPackageSeq_;

    //
    // List of generated files
    //
    IdlStringSeq* fileNameSeq_;

    //
    // If set, generate everything relative to this package
    //
    const char* package_;

    //
    // Cache for absolute names and packages
    //
    IdlStringSeq absSeq_;
    IdlStringSeq pkgSeq_;

    //
    // If true, automatically build package names from prefixes
    //
    bool autoPackage_;

    //
    // If true, don't add comments in generated code
    //
    bool noComments_;

    //
    // If true, create locality-constrained objects
    //
    bool local_;

    //
    // If true, generate clone() methods for data types
    //
    bool clone_;

    //
    // If set, write .java files to this path
    //
    const char* outDir_;

    //
    // Print header comment
    //
    void comment(const char*, IdlPrettyPrint&);

    //
    // Print documentation comment
    //
    void docComment(const char*, IdlPrettyPrint&);

    //
    // Precede Java keywords and reserved names by an underscore
    //
    char* fixName(const char*);

    //
    // Create type string
    //
    enum GetType
    {
	GetTypeNormal,   // Normal type string
	GetTypeHolder,   // Holder type string
	GetTypeHelper,   // Helper type string
	GetTypeStub      // Stub type string
    };
    
    char* getTypeString(const char*, CORBA_TypeCode_ptr,
			GetType = GetTypeNormal);

    //
    // Check if code needs to be generated for a specific repository id
    //
    bool check(const char*);

    //
    // Get package from package options
    //
    char* getPackageFromOptions(const char*);

    //
    // Get absolute name
    //
    char* getAbsolute(const char*);
    char* getAbsolute(CORBA_Contained_ptr);
    char* getAbsolutePackage(CORBA_Contained_ptr, const char*);

    //
    // Get package
    //
    char* getPackage(const char*);
    char* getPackage(CORBA_Contained_ptr);
    char* getPackagePackage(CORBA_Contained_ptr, const char*);

    //
    // Build package name from prefix in repository id
    //
    char* getPackageFromPrefix(const char*);

    //
    // Get scope
    //
    char* getScope(CORBA_Container_ptr);

    //
    // Convert strings with escape sequences
    //
    static void addEscapes(char*&, bool);

    //
    // Remove package from absolute name
    //
    static void removePackage(const char*, char*&);

    //
    // Get union label sequence
    //
    IdlStringSeq* getUnionLabelSeq(const char*, CORBA_TypeCode_ptr,
				   const IdlUnionMemberInfo&);

    //
    // Get holder class for a union member
    //
    char *getUnionMemberHolder(CORBA_TypeCode_ptr);

    //
    // Determines if the typecode is a primitive (or immutable) type
    //
    bool isPrimitiveMemberType(CORBA_TypeCode_ptr tc);

    //
    // Generate Java code
    //
    int genJava(CORBA_Container_ptr, IdlPrettyPrint&);

    //
    // Generate Java skeleton code, general part
    //
    int genJavaSkel(CORBA_Container_ptr, IdlPrettyPrint&);

    //
    // Generate Java skeleton code, private part
    //
    int genJavaSkelPrivate(CORBA_Container_ptr, const char* , IdlPrettyPrint&);

    //
    // Generate Java tie code
    //
    int genJavaTie(CORBA_Container_ptr, IdlPrettyPrint&);

    //
    // Write constants
    //
    void writeConstant(const CORBA_Any&, IdlPrettyPrint&);

    //
    // Write the holder class
    //
    void writeHolder(const char*, const char*, IdlPrettyPrint&);

    //
    // Write the helper class
    //
    void writeHelper(const char*, CORBA_TypeCode_ptr, IdlPrettyPrint&);

    //
    // Write TypeCode
    //
    void writeTypeCode(const char*, const char*, CORBA_TypeCode_ptr,
		       IdlPrettyPrint&);

    //
    // Write stream read/write functions
    //
    void writeReaderWriter(const char*, CORBA_TypeCode_ptr,
			   const char*, CORBA_ULong&,
			   bool, IdlPrettyPrint&);

    //
    // Write any insertion/extraction for stubs/skeletons
    //
    void writeInsertExtract(const char*, CORBA_TypeCode_ptr, const char*, bool,
			    IdlPrettyPrint&);

    //
    // Write clone() method
    //
    void writeClone(CORBA_DefinitionKind kind, const char*, const char*,
		    CORBA_TypeCode_ptr, IdlPrettyPrint&);

    //
    // Write clone() assignment code for struct/union/except member
    //
    void writeMemberClone(const char*, const char*, const char*,
			  CORBA_TypeCode_ptr, const char*, IdlPrettyPrint&,
			  int);

public:

    IdlJavaGenerator(const char*, CORBA_Repository_ptr,
		     const CORBA_RepositoryIdSeq&, const IdlCommentSeq&,
		     const IdlPrefixPackageSeq&, IdlStringSeq*&, const char*,
		     bool, bool, bool, bool, const char*);
    
    IdlJavaGenerator(const char*, CORBA_Repository_ptr,
		     const IdlCommentSeq&,
		     const IdlPrefixPackageSeq&, IdlStringSeq*&, const char*,
		     bool, bool, bool, bool, const char*);

    //
    // Generate Java code
    //
    int gen();
    int genSkel();
    int genTie();
};

#endif
