root/src/kits/debugger/value/ValueNode.cpp
/*
 * Copyright 2015, Rene Gollent, rene@gollent.com.
 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Distributed under the terms of the MIT License.
 */


#include "ValueNode.h"

#include "Value.h"
#include "ValueLocation.h"
#include "ValueNodeContainer.h"


// #pragma mark - ValueNode


ValueNode::ValueNode(ValueNodeChild* nodeChild)
        :
        fContainer(NULL),
        fNodeChild(nodeChild),
        fLocation(NULL),
        fValue(NULL),
        fLocationResolutionState(VALUE_NODE_UNRESOLVED),
        fChildrenCreated(false)
{
        fNodeChild->AcquireReference();
}


ValueNode::~ValueNode()
{
        SetLocationAndValue(NULL, NULL, VALUE_NODE_UNRESOLVED);
        SetContainer(NULL);
        fNodeChild->ReleaseReference();
}


const BString&
ValueNode::Name() const
{
        return fNodeChild->Name();
}


void
ValueNode::SetContainer(ValueNodeContainer* container)
{
        if (container == fContainer)
                return;

        if (fContainer != NULL)
                fContainer->ReleaseReference();

        fContainer = container;

        if (fContainer != NULL)
                fContainer->AcquireReference();

        // propagate to children
        int32 childCount = CountChildren();
        for (int32 i = 0; i < childCount; i++)
                ChildAt(i)->SetContainer(fContainer);
}


bool
ValueNode::IsRangedContainer() const
{
        return false;
}


bool
ValueNode::IsContainerRangeFixed() const
{
        return false;
}


void
ValueNode::ClearChildren()
{
        // do nothing
}


status_t
ValueNode::CreateChildrenInRange(TeamTypeInformation* info, int32 lowIndex,
        int32 highIndex)
{
        return B_NOT_SUPPORTED;
}


status_t
ValueNode::SupportedChildRange(int32& lowIndex, int32& highIndex) const
{
        return B_NOT_SUPPORTED;
}


void
ValueNode::SetLocationAndValue(ValueLocation* location, Value* value,
        status_t resolutionState)
{
        if (fLocation != location) {
                if (fLocation != NULL)
                        fLocation->ReleaseReference();

                fLocation = location;

                if (fLocation != NULL)
                        fLocation->AcquireReference();
        }

        if (fValue != value) {
                if (fValue != NULL)
                        fValue->ReleaseReference();

                fValue = value;

                if (fValue != NULL)
                        fValue->AcquireReference();
        }

        fLocationResolutionState = resolutionState;

        // notify listeners
        if (fContainer != NULL)
                fContainer->NotifyValueNodeValueChanged(this);
}


// #pragma mark - ValueNodeChild


ValueNodeChild::ValueNodeChild()
        :
        fContainer(NULL),
        fNode(NULL),
        fLocation(NULL),
        fLocationResolutionState(VALUE_NODE_UNRESOLVED)
{
}


ValueNodeChild::~ValueNodeChild()
{
        SetLocation(NULL, VALUE_NODE_UNRESOLVED);
        SetNode(NULL);
        SetContainer(NULL);
}


bool
ValueNodeChild::IsInternal() const
{
        return false;
}


status_t
ValueNodeChild::CreateInternalNode(ValueNode*& _node)
{
        return B_BAD_VALUE;
}


void
ValueNodeChild::SetContainer(ValueNodeContainer* container)
{
        if (container == fContainer)
                return;

        if (fContainer != NULL)
                fContainer->ReleaseReference();

        fContainer = container;

        if (fContainer != NULL)
                fContainer->AcquireReference();

        // propagate to node
        if (fNode != NULL)
                fNode->SetContainer(fContainer);
}


void
ValueNodeChild::SetNode(ValueNode* node)
{
        if (node == fNode)
                return;

        ValueNode* oldNode = fNode;
        BReference<ValueNode> oldNodeReference(oldNode, true);

        if (fNode != NULL)
                fNode->SetContainer(NULL);

        fNode = node;

        if (fNode != NULL) {
                fNode->AcquireReference();
                fNode->SetContainer(fContainer);
        }

        if (fContainer != NULL)
                fContainer->NotifyValueNodeChanged(this, oldNode, fNode);
}


ValueLocation*
ValueNodeChild::Location() const
{
        return fLocation;
}


void
ValueNodeChild::SetLocation(ValueLocation* location, status_t resolutionState)
{
        if (fLocation != location) {
                if (fLocation != NULL)
                        fLocation->ReleaseReference();

                fLocation = location;

                if (fLocation != NULL)
                        fLocation->AcquireReference();
        }

        fLocationResolutionState = resolutionState;
}


// #pragma mark - ChildlessValueNode


ChildlessValueNode::ChildlessValueNode(ValueNodeChild* nodeChild)
        :
        ValueNode(nodeChild)
{
        fChildrenCreated = true;
}


status_t
ChildlessValueNode::CreateChildren(TeamTypeInformation* info)
{
        return B_OK;
}

int32
ChildlessValueNode::CountChildren() const
{
        return 0;
}


ValueNodeChild*
ChildlessValueNode::ChildAt(int32 index) const
{
        return NULL;
}