/***************************************************************************
 *   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) 2003      Brian Thomas <thomas@mail630.gsfc.nasa.gov>   *
 *   copyright (C) 2004-2020                                               *
 *   Umbrello UML Modeller Authors <umbrello-devel@kde.org>                *
 ***************************************************************************/

#include "codeclassfielddeclarationblock.h"

#include "codeclassfield.h"
#include "umlrole.h"

/**
 * Constructor.
 */
CodeClassFieldDeclarationBlock::CodeClassFieldDeclarationBlock(CodeClassField * parentCF)
        : OwnedCodeBlock((UMLObject*) parentCF->getParentObject()),
          CodeBlockWithComments((CodeDocument*) parentCF->getParentDocument())
{
    init(parentCF);
}

/**
 * Empty Destructor
 */
CodeClassFieldDeclarationBlock::~CodeClassFieldDeclarationBlock()
{
    // Q: is this needed??
    //      m_parentclassfield->getParentObject()->disconnect(this);
}

/**
 * Get the value of m_parentclassfield.
 * @return the value of m_parentclassfield
 */
CodeClassField * CodeClassFieldDeclarationBlock::getParentClassField()
{
    return m_parentclassfield;
}

/**
 * A utility method to get the parent object of the parentCodeClassfield.
 */
UMLObject * CodeClassFieldDeclarationBlock::getParentObject()
{
    return m_parentclassfield->getParentObject();
}

// this type of textblock is special
// we DON'T release it when resetTextBlocks is
// called because we re-use it over and over
// until the codeclassfield is released.
void CodeClassFieldDeclarationBlock::release()
{
    // do nothing
}

/**
 * So parent can actually release this block.
 */
void CodeClassFieldDeclarationBlock::forceRelease()
{
    if (m_parentclassfield)
    {
        // m_parentclassfield->getParentObject()->disconnect(this);
        m_parentclassfield->disconnect(this);
    }
    m_parentclassfield = 0;
    OwnedCodeBlock::release();
    TextBlock::release();
}

/**
 * Save the XMI representation of this object.
 */
void CodeClassFieldDeclarationBlock::saveToXMI1(QDomDocument & doc, QDomElement & elem)
{
    QDomElement docElement = doc.createElement(QLatin1String("ccfdeclarationcodeblock"));
    setAttributesOnNode(doc, docElement);
    elem.appendChild(docElement);
}

/**
 * Load params from the appropriate XMI element node.
 */
void CodeClassFieldDeclarationBlock::loadFromXMI1 (QDomElement & root)
{
    setAttributesFromNode(root);
}

/**
 * Set attributes of the node that represents this class
 * in the XMI document.
 */
void CodeClassFieldDeclarationBlock::setAttributesOnNode (QDomDocument & doc, QDomElement & elem)
{
    // set super-class attributes
    CodeBlockWithComments::setAttributesOnNode(doc, elem);
    OwnedCodeBlock::setAttributesOnNode(doc, elem);
}

/**
 * Set the class attributes of this object from
 * the passed element node.
 */
void CodeClassFieldDeclarationBlock::setAttributesFromNode(QDomElement & root)
{
    // set attributes from the XMI
    CodeBlockWithComments::setAttributesFromNode(root); // superclass load
    OwnedCodeBlock::setAttributesFromNode(root); // superclass load

    syncToParent();
}

/**
 * Set the class attributes from a passed object.
 */
void CodeClassFieldDeclarationBlock::setAttributesFromObject (TextBlock * obj)
{
    CodeBlockWithComments::setAttributesFromObject(obj);

    CodeClassFieldDeclarationBlock * ccb = dynamic_cast<CodeClassFieldDeclarationBlock*>(obj);
    if (ccb)
    {
        m_parentclassfield->disconnect(this);
        init(ccb->getParentClassField());

        syncToParent();
    }
}

void CodeClassFieldDeclarationBlock::syncToParent ()
{
    // for role-based accessors, we DON'T write ourselves out when
    // the name of the role is not defined.
    if (!(getParentClassField()->parentIsAttribute()))
    {
        UMLRole * parent = getParentObject()->asUMLRole();
        if (parent == 0)
            return;
        if (parent->name().isEmpty())
        {
            getComment()->setWriteOutText(false);
            setWriteOutText(false);
        } else {
            getComment()->setWriteOutText(true);
            setWriteOutText(true);
        }
    }

    // only update IF we are NOT AutoGenerated
    if (contentType() != AutoGenerated)
        return;

    updateContent();
}

void CodeClassFieldDeclarationBlock::init (CodeClassField * parentCF)
{
    m_parentclassfield = parentCF;
    setCanDelete(false);
    connect(m_parentclassfield, SIGNAL(modified()), this, SLOT(syncToParent()));
}

