/***************************************************************************
 *   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-2011                                               *
 *   Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                  *
 ***************************************************************************/

/**
 * Basicially a class to allow for synchronization of the contents based on the
 * values of the parentClassField's parentObject
 */

#include "codeclassfielddeclarationblock.h"

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

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

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::saveToXMI ( QDomDocument & doc, QDomElement & elem)
{
    QDomElement docElement = doc.createElement( "ccfdeclarationcodeblock" );
    setAttributesOnNode(doc, docElement);
    elem.appendChild( docElement );
}

/**
 * Load params from the appropriate XMI element node.
 */
void CodeClassFieldDeclarationBlock::loadFromXMI ( 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 = dynamic_cast<UMLRole*>(getParentObject());
        if (parent == NULL)
            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()));
}

#include "codeclassfielddeclarationblock.moc"
