/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 *   copyright (C) 2004-2006                                               *
 *   Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                  *
 ***************************************************************************/

/*  This code generated by:
 *      Author : thomas
 *      Date   : Mon Sep 1 2003
 */

#include "cppsourcecodeoperation.h"

#include "cppcodegenerator.h"
#include "cppcodegenerationpolicy.h"
#include "cppsourcecodedocument.h"
#include "cppcodedocumentation.h"
#include "../uml.h"

// Constructors/Destructors
//

CPPSourceCodeOperation::CPPSourceCodeOperation ( CPPSourceCodeDocument * doc, UMLOperation *parent, const TQString & body, const TQString & comment )
        : CodeOperation (doc, parent, body, comment)
{
    // lets not go with the default comment and instead use
    // full-blown cpp documentation object instead
    setComment(new CPPCodeDocumentation(doc));

    // these things never change..
    setOverallIndentationLevel(0);
    setEndMethodText("}");

    //updateMethodDeclaration();
    CodeGenPolicyExt * pe = UMLApp::app()->getPolicyExt();
    CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
    UMLClassifier * c = doc->getParentClassifier();
    UMLOperation * o = getParentOperation();
    bool isInterface = doc->parentIsInterface();
    bool isInlineMethod = policy->getOperationsAreInline( );

    // first, the comment on the operation
    TQString cmnt = o->getDoc();
    getComment()->setText(cmnt);

    TQString returnType = o->getTypeName();
    TQString methodName = o->getName();
    TQString paramStr = TQString("");
    TQString className = CodeGenerator::cleanName(c->getName());

    // assemble parameters
    UMLAttributeList list = getParentOperation()->getParmList();
    int nrofParam = list.count();
    int paramNum = 0;
    for(UMLAttribute* parm = list.first(); parm; parm=list.next())
    {
        TQString rType = parm->getTypeName();
        TQString paramName = parm->getName();
        paramStr += rType + ' ' + paramName;
        paramNum++;

        if (paramNum != nrofParam )
            paramStr  += ", ";
    }

    // no return type for constructors/destructors
    if (o->isLifeOperation())
        returnType = "";
    // if an operation isn't a constructor/destructor and it has no return type
    // this operation should be  void
    else if (returnType.isEmpty())
        returnType = TQString("void");

    TQString startText = returnType + ' ';

    // if a property has a friend stereotype, the operation should
    // not be a class name
    if (o->getStereotype() != "friend")
        startText += className + "::";
    startText += methodName + " (" + paramStr + ')';
    if (o->getConst())
        startText += " const";
    startText += " {";

    setStartMethodText(startText);

    // Only write this out if its a child of an interface OR is abstract.
    // and its not inline
    if(isInterface || o->getAbstract() || isInlineMethod)
    {
        setWriteOutText(false);
    } else {
        setWriteOutText(true);
    }


    updateContent();
}

CPPSourceCodeOperation::~CPPSourceCodeOperation ( ) { }

// Other methods
//

// we basically just want to know whether or not to print out
// the body of the operation.
// In C++ if the operations are inline, then we DONT print out
// the body text.
void CPPSourceCodeOperation::updateContent( )
{
    CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
    CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
    bool isInlineMethod = policy->getOperationsAreInline();

    if(!isInlineMethod)
        setText(""); // change whatever it is to "";

}

// we basically want to update the doc and start text of this method
void CPPSourceCodeOperation::updateMethodDeclaration()
{

    CPPSourceCodeDocument * doc = dynamic_cast<CPPSourceCodeDocument*>(getParentDocument());
    CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
    CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
    UMLClassifier * c = doc->getParentClassifier();
    UMLOperation * o = getParentOperation();
    bool isInterface = doc->parentIsInterface();
    bool isInlineMethod = policy->getOperationsAreInline( );

    // first, the comment on the operation
    TQString comment = o->getDoc();
    getComment()->setText(comment);

    TQString returnType = o->getTypeName();
    TQString methodName = o->getName();
    TQString paramStr = TQString("");
    TQString className = CodeGenerator::cleanName(c->getName());

    // assemble parameters
    UMLAttributeList list = getParentOperation()->getParmList();
    int nrofParam = list.count();
    int paramNum = 0;
    for(UMLAttribute* parm = list.first(); parm; parm=list.next())
    {
        TQString rType = parm->getTypeName();
        TQString paramName = parm->getName();
        paramStr += rType + ' ' + paramName;
        paramNum++;

        if (paramNum != nrofParam )
            paramStr  += ", ";
    }

    // no return type for constructors/destructors
    if (o->isLifeOperation())
        returnType = "";
    // if an operation isn't a constructor/destructor and it has no return type
    // this operation should be  void
    else if (returnType.isEmpty())
        returnType = TQString("void");

    TQString startText = returnType + ' ';

    // if a property has a friend stereotype, the operation should
    // not be a class name
    if (o->getStereotype() != "friend")
        startText += className + "::";
    startText += methodName + " (" + paramStr + ')';
    if (o->getConst())
        startText += " const";
    startText += " {";

    setStartMethodText(startText);

    // Only write this out if its a child of an interface OR is abstract.
    // and its not inline
    if(isInterface || o->getAbstract() || isInlineMethod)
    {
        setWriteOutText(false);
    } else {
        setWriteOutText(true);
    }

}

#include "cppsourcecodeoperation.moc"
