/***************************************************************************
                          cppwriter.h  -  description
    This is the "old" code generator that does not support code editing
    in the Modeller but uses significantly less file space because the
    source code is not replicated in the XMI file.
                             -------------------
    copyright            : (C) 2003 Brian Thomas
         (C) 2004  Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef CPPWRITER_H
#define CPPWRITER_H

#include "simplecodegenerator.h"
#include "cppcodegenerationpolicy.h"
#include "../umloperationlist.h"
#include "../umlattributelist.h"
#include "../umlassociationlist.h"

class TQFile;
class ClassifierInfo;

/**
  * class CppWriter is a code generator for UMLClassifier objects.
  * Create an instance of this class, and feed it a UMLClassifier when
  * calling writeClass and it will generate both a header (.h) and
  * source (.cpp) file for that classifier.
  */
class CppWriter : public SimpleCodeGenerator {
public:

    /**
     * Constructor, initialises a couple of variables
     */
    CppWriter();

    /**
     * Destructor, empty
     */
    virtual ~CppWriter();

    /**
     * call this method to generate cpp code for a UMLClassifier
     * @param c the class to generate code for
     */
    virtual void writeClass(UMLClassifier *c);

    /**
     * returns "C++"
     */
    virtual Uml::Programming_Language getLanguage();

    /**
     * Add C++ primitives as datatypes
     */
    TQStringList defaultDatatypes();

    /**
     * get list of reserved keywords
     */
    virtual const TQStringList reservedKeywords() const;

private:

    /**
     * Writes class's documentation to the class header
     * public abstract class Foo extents {
     */
    void writeClassDecl(UMLClassifier *c, TQTextStream &cpp);

    /**
     * Writes the comment and class constructor declaration or methods
     */
    void writeConstructorDecls(TQTextStream &h);
    void writeConstructorMethods(TQTextStream &cpp);

    /**
     * write all field declarations, for both attributes and associations for the
     * given permitted scope.
     */
    void writeFieldDecl(UMLClassifier *c, Uml::Visibility permitScope, TQTextStream &stream);

    /**
     * write all method declarations, for attributes and associations
     * for the given permitted scope.
     */
    void writeAccessorMethodDecl(UMLClassifier *c, Uml::Visibility permitScope, TQTextStream &stream);

    /**
     * write all operations for a given class
     * @param c the class for which we are generating code
     * @param isHeaderMethod true when writing to a header file, false for body file
     * @param permitScope what type of method to write (by Scope)
     * @param j the stream associated with the output file
     */
    void writeOperations(UMLClassifier *c, bool isHeaderMethod, Uml::Visibility permitScope, TQTextStream &j);

    /**
     * write a list of operations for a given class
     * @param list the list of operations you want to write
     * @param isHeaderMethod true when writing to a header file, false for body file
     * @param j the stream associated with the output file
     */
    void writeOperations(UMLOperationList &list, bool isHeaderMethod, TQTextStream &j);

    /**
     * write all attributes for a given class
     * @param c the class for which we are generating code
     * @param j the stream associated with the output file
     */
    void writeAttributes(UMLClassifier *c, TQTextStream &j);

    /**
     * writes the Attribute declarations
     * @param visibility the visibility of the attribs to print out
     * @param writeStatic whether to write static or non-static attributes out
     * @param stream text stream
     */
    void writeAttributeDecls (Uml::Visibility visibility, bool writeStatic, TQTextStream &stream );

    /**
     * Write out fields and operations for this class selected on a particular
     * visibility.
     */
    void writeHeaderFieldDecl(UMLClassifier *c, Uml::Visibility permitVisibility, TQTextStream &stream);

    void writeHeaderAttributeAccessorMethods (Uml::Visibility visibility, bool writeStatic, TQTextStream &stream );

    void writeHeaderAttributeAccessorMethodDecls(UMLClassifier *c, Uml::Visibility permitVisibility, TQTextStream &stream);
    void writeHeaderAccessorMethodDecl(UMLClassifier *c, Uml::Visibility permitScope, TQTextStream &stream);


    /**
     * Searches a list of associations for appropriate ones to write out as attributes
     */
    void writeAssociationDecls(UMLAssociationList associations, Uml::Visibility permit, Uml::IDType id, TQTextStream &stream);

    /**
     * Writes out an association as an attribute using Vector
     */
    void writeAssociationRoleDecl(TQString fieldClassName, TQString roleName, TQString multi,
                                  TQString doc, TQTextStream &stream);

    /**
     * calls @ref writeSingleAttributeAccessorMethods() on each of the attributes in attribs list.
     */
    void writeAttributeMethods(UMLAttributeList *attribs, Uml::Visibility visib, bool isHeaderMethod,
                               bool isStatic,
                               bool writeMethodBody, TQTextStream &stream);

    /**
     * calls @ref writeAssociationRoleMethod() on each of the associations in the given list
     */
    void writeAssociationMethods(UMLAssociationList associations, Uml::Visibility permitVisib,
                                 bool isHeaderMethod,
                                 bool writeMethodBody, bool writePointerVar, Uml::IDType id, TQTextStream &stream);

    /**
     * calls @ref writeSingleAttributeAccessorMethods() or @ref
     * writeVectorAttributeAccessorMethods() on the association
     * role
     */
    void writeAssociationRoleMethod(const TQString &fieldClassName, bool isHeaderMethod, bool writeMethodBody,
                                    const TQString &roleName, const TQString &multi,
                                    const TQString &description, Uml::Changeability_Type change,
                                    TQTextStream &stream);

    /**
     * Writes getFoo() and setFoo() accessor methods for the attribute
     */
    void writeSingleAttributeAccessorMethods(
            const TQString &fieldClassName, const TQString &Name,
            const TQString &fieldName, const TQString &description,
            Uml::Changeability_Type change,
            bool isHeaderMethod,
            bool isStatic, bool writeMethodBody, TQTextStream &cpp);

    /**
     * Writes addFoo() and removeFoo() accessor methods for the Vector attribute
     */
    void writeVectorAttributeAccessorMethods(
            const TQString &fieldClassName, const TQString &fieldVarName,
            const TQString &fieldName, const TQString &description,
            Uml::Changeability_Type change,
            bool isHeaderMethod,
            bool writeMethodBody,
            TQTextStream &cpp);

    /**
     * Writes a // style comment
     */
    void writeComment(const TQString &text, const TQString &indent, TQTextStream &cpp);

    /**
     * Writes a documentation comment
     */
    void writeDocumentation(TQString header, TQString body, TQString end, TQTextStream &cpp);


    /**
     * write the header file for this classifier.
     */
    void writeHeaderFile (UMLClassifier *c, TQFile &file);

    /**
     * write the source code body file for this classifier.
     */
    void writeSourceFile (UMLClassifier *c, TQFile &file);

    /**
     * utility method to break up a block of text, which has embedded newline chars,
     * and print them to a stream as separate lines of text, indented as directed.
     */
    void printTextAsSeparateLinesWithIndent (const TQString &text, const TQString &indent,
                                             TQTextStream &stream);

    /**
     * Intellegently print out header include/forward decl. for associated classes.
     */
    void printAssociationIncludeDecl (UMLAssociationList list, Uml::IDType this_id, TQTextStream &stream);

    /**
     * If needed, write out the method to initialize attributes of our class.
     */
    void writeInitAttibuteMethod (TQTextStream &stream);

    /**
     * If needed, write out the declaration for the method to initialize attributes of our class.
     */
    void writeInitAttibuteDecl (TQTextStream &stream);

    /**
     * Returns the name of the given object (if it exists)
     */
    TQString getUMLObjectName(UMLObject *obj);

    /**
     * Replaces `string' with STRING_TYPENAME.
     */
    TQString fixTypeName(const TQString &string);

    /**
     * check that initial values of strings have quotes around them
     */
    TQString fixInitialStringDeclValue(const TQString &value, const TQString &type);

    /**
     * Determine what the variable name of this attribute should be.
     */
    TQString getAttributeVariableName (UMLAttribute *at);

    /**
     * Write a blank line
     */
    void writeBlankLine(TQTextStream &stream);

    /**
     * Return the policy object
     */
    CPPCodeGenerationPolicy *policyExt();

    /**
     * Summary information about current classifier.
     */
    ClassifierInfo * m_classifierInfo;

    TQString VECTOR_METHOD_APPEND;
    TQString VECTOR_METHOD_REMOVE;
    TQString VECTOR_METHOD_INIT;
    TQString OBJECT_METHOD_INIT;

    /**
     * Create association methods for class attributes/associations/operations as inline decl in header.
     */
    bool INLINE_ASSOCIATION_METHODS;

    TQStringList ObjectFieldVariables;
    TQStringList VectorFieldVariables;

};



#endif // CPPWRITER_H
