/* $Id: ProjectFolder.cpp 431215 2014-04-02 14:55:10Z katargir $
 * ===========================================================================
 *
 *                            PUBLIC DOMAIN NOTICE
 *               National Center for Biotechnology Information
 *
 *  This software/database is a "United States Government Work" under the
 *  terms of the United States Copyright Act.  It was written as part of
 *  the author's official duties as a United States Government employee and
 *  thus cannot be copyrighted.  This software/database is freely available
 *  to the public for use. The National Library of Medicine and the U.S.
 *  Government have not placed any restriction on its use or reproduction.
 *
 *  Although all reasonable efforts have been taken to ensure the accuracy
 *  and reliability of the software and data, the NLM and the U.S.
 *  Government do not and cannot warrant the performance or results that
 *  may be obtained by using this software or data. The NLM and the U.S.
 *  Government disclaim all warranties, express or implied, including
 *  warranties of performance, merchantability or fitness for any particular
 *  purpose.
 *
 *  Please cite the author in any work or product based on this material.
 *
 * ===========================================================================
 *
 * Author:  .......
 *
 * File Description:
 *   .......
 *
 * Remark:
 *   This code was originally generated by application DATATOOL
 *   using the following specifications:
 *   'gbproj.asn'.
 */

// standard includes
#include <ncbi_pch.hpp>

// generated includes
#include <objects/gbproj/ProjectFolder.hpp>
#include <serial/iterator.hpp>

// generated classes

BEGIN_NCBI_SCOPE

BEGIN_objects_SCOPE // namespace ncbi::objects::

CAtomicCounter CProjectFolder::m_IdCounter;

// destructor
CProjectFolder::~CProjectFolder(void)
{
}


/// CIdSelector finds a Project Item by Id
class CPrjItemSelector_Id : public CProjectFolder::IProjectItemVisitor
{
public:
    CPrjItemSelector_Id(CProjectItem::TId id)
        : m_Id(id), m_Item(NULL)  {}

    virtual bool    Visit(CProjectItem& item)
    {
        if(item.GetId() == m_Id)  {
            m_Item = &item;
            return false; // stop iterating
        }
        return true; // continue
    }

public:
    CProjectItem::TId m_Id;
    CProjectItem*   m_Item;
};


/// CLabelSelector finds a Project Item by Label
class CPrjItemSelector_Label : public CProjectFolder::IProjectItemVisitor
{
public:
    CPrjItemSelector_Label(const string& label)
        : m_Label(label), m_Item(NULL)  {}

    virtual bool    Visit(CProjectItem& item)
    {
        if(item.GetLabel() == m_Label)  {
            m_Item = &item;
            return false; // stop iterating
        }
        return true; // continue
    }

public:
    string  m_Label;
    CProjectItem*   m_Item;
};


class CPrjItemSelector_Data : public CProjectFolder::IProjectItemVisitor
{
public:
    CPrjItemSelector_Data(const CSerialObject& object)
        : m_Object(&object), m_Item(NULL)  {}

    virtual bool    Visit(CProjectItem& item)
    {
        if(item.GetObject() == m_Object)  {
            m_Item = &item;
            return false; // stop iterating
        }
        return true; // continue
    }

public:
    const CSerialObject*    m_Object;
    CProjectItem*   m_Item;
};


CProjectItem* CProjectFolder::FindProjectItemByLabel(const string& label)
{
    CPrjItemSelector_Label selector(label);
    ForEachProjectItem(selector, false);
    return selector.m_Item;
}


const CProjectItem* CProjectFolder::GetProjectItem(CProjectItem::TId id) const
{
    if (!CanGetItems())
        return 0;

    ITERATE (TItems, it, GetItems()) {
        if ((*it)->GetId() == id) {
            return *it;
        }
    }
    return 0;
}


CProjectItem* CProjectFolder::GetProjectItem(CProjectItem::TId id)
{
    const CProjectItem* item = const_cast<const CProjectFolder&>(*this).GetProjectItem(id);
    return const_cast<CProjectItem*>(item);
}


const CProjectFolder* CProjectFolder::GetProjectFolder(CProjectFolder::TId id) const
{
    if (!CanGetFolders())
        return 0;

    ITERATE (TFolders, it, GetFolders()) {
        if ((*it)->GetId() == id) {
            return *it;
        }
    }
    return 0;
}


CProjectFolder* CProjectFolder::GetProjectFolder(CProjectFolder::TId id)
{
    const CProjectFolder* item = const_cast<const CProjectFolder&>(*this).GetProjectFolder(id);
    return const_cast<CProjectFolder*>(item);
}


const CProjectItem* CProjectFolder::FindProjectItemById(CProjectItem::TId id) const
{
    const CProjectItem* item = 0;
    for (CTypeConstIterator<CProjectItem> it(*this);  it;  ++it) {
        if (it->GetId() == id) {
            item = &*it;
            break;
        }
    }
    return item;
}

CProjectItem* CProjectFolder::FindProjectItemById(CProjectItem::TId id)
{
    const CProjectItem* item = const_cast<const CProjectFolder&>(*this).FindProjectItemById(id);
    return const_cast<CProjectItem*>(item);
}


CProjectItem* CProjectFolder::FindProjectItemByData(const CSerialObject& object,
                                                    bool recursive)
{
    CPrjItemSelector_Data selector(object);
    ForEachProjectItem(selector, recursive);
    return selector.m_Item;
}


const CProjectFolder* CProjectFolder::FindChildFolderById(TId id) const
{
    const CProjectFolder* folder = 0;
    for (CTypeConstIterator<CProjectFolder> it(*this);  it;  ++it) {
        if (this == &*it)
            continue;
        if (it->GetId() == id) {
            folder = &*it;
            break;
        }
    }

    return folder;
}


CProjectFolder* CProjectFolder::FindChildFolderById(TId id)
{
    const CProjectFolder* parent = const_cast<const CProjectFolder&>(*this).FindChildFolderById(id);
    return const_cast<CProjectFolder*>(parent);
}


CProjectFolder* CProjectFolder::FindChildFolderByTitle(const string& title)
{
    NON_CONST_ITERATE(TFolders, it, SetFolders())    {
        CProjectFolder& child = **it;
        if(child.SetInfo().SetTitle() == title)   {
            return &child;
        }
    }
    return NULL; // not found
}

const CProjectFolder* CProjectFolder::FindProjectItemFolder(CProjectItem::TId id) const
{
    for (CTypeConstIterator<CProjectFolder> it(*this);  it;  ++it) {
        if (it->GetProjectItem(id)) {
            return &*it;
        }
    }
    return 0;
}

CProjectFolder* CProjectFolder::FindProjectItemFolder(CProjectItem::TId id)
{
    const CProjectFolder* parent = const_cast<const CProjectFolder&>(*this).FindProjectItemFolder(id);
    return const_cast<CProjectFolder*>(parent);
}

CRef<CProjectFolder> CProjectFolder::RemoveProjectFolder(CProjectFolder::TId id)
{
    for (CTypeIterator<CProjectFolder> it(*this);  it;  ++it) {
        CProjectFolder::TFolders& folders = it->SetFolders();
        for (CProjectFolder::TFolders::iterator it2 = folders.begin(); it2 != folders.end(); ++it2) {
            if ((*it2)->GetId() == id) {
                CRef<CProjectFolder> removed(*it2);
                folders.erase(it2);
                return removed;
            }
        }
    }
    return CRef<CProjectFolder>();
}

void CProjectFolder::AddChildItem(CProjectItem& child_item)
{
    CRef<CProjectItem> ref(&child_item);
    TItems& items = SetItems();
    items.push_back(ref);
}


bool CProjectFolder::RemoveChildItem(CProjectItem& child_item)
{
    if(IsSetItems())    {
        CRef<CProjectItem> ref(&child_item);
        TItems& items = SetItems();
        TItems::iterator it = std::find(items.begin(), items.end(), ref);
        if(it != items.end())   {
            items.erase(it);
            return true;
        }
    }
    return false;
}


bool CProjectFolder::RemoveChildItem(CProjectItem::TId id)
{
    if(IsSetItems())    {
        TItems& items = SetItems();
        NON_CONST_ITERATE(TItems, it, items)    {
            CProjectItem& item = **it;
            if(item.GetId() == id)   {
                items.erase(it);
                return true;
            }
        }
    }
    return false;
}


void CProjectFolder::RemoveAllChildItems()
{
    if(IsSetItems())    {
        TItems& items = SetItems();
        NON_CONST_ITERATE(TItems, it, items)    {
            CProjectItem& item = **it;
        }
        items.clear();
    }
}


void CProjectFolder::AddChildFolder(CProjectFolder& child_folder)
{
    CRef<CProjectFolder> ref(&child_folder);
    TFolders& folders = SetFolders();
    folders.push_back(ref);
}


void CProjectFolder::RemoveChildFolder(CProjectFolder& child_folder)
{
    TFolders& folders = SetFolders();
    CRef<CProjectFolder> ref(&child_folder);
    TFolders::iterator it = std::find(folders.begin(), folders.end(), ref);

    if(it !=  folders.end())    {
        folders.erase(it);
    } else {
        NCBI_THROW(CException, eUnknown, "Folder is not found.");
    }
}


void CProjectFolder::RemoveChildFolder(CProjectFolder::TId folder_id)
{
    TFolders& folders = SetFolders();
    NON_CONST_ITERATE(TFolders, it, folders)  {
        CProjectFolder& sub_folder = **it;
        if(sub_folder.GetId() == folder_id) {
            folders.erase(it);
            return;
        }
    }
    NCBI_THROW(CException, eUnknown, "Folder is not found.");
}

bool CProjectFolder::ForEachProjectItem(IProjectItemVisitor& visitor,
                                    bool recursive)
{
    bool ok = true;

    if(IsSetItems())    {
        //  iterate through Project Items in this Folder
        TItems& items = SetItems();
        NON_CONST_ITERATE(TItems, it, items)    {
            CProjectItem& item = **it;
            ok = visitor.Visit(item);
            if( ! ok)
                return false;
        }
    }

    if(recursive)   {
        // recursively iterate through child Folders
        TFolders& folders = SetFolders();
        NON_CONST_ITERATE(TFolders, it, folders)    {
            CProjectFolder& child = **it;
            ok = child.ForEachProjectItem(visitor, true);
            if( ! ok) {
                return false;
            }
        }
    }
    return true;
}


END_objects_SCOPE // namespace ncbi::objects::

END_NCBI_SCOPE

/* Original file checksum: lines: 57, chars: 1734, CRC32: b33bdb51 */
