/*
 * Copyright 2009 Funambol, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* $Id$ */

#include "CMemoryDataStorage.h"
#include "MemoryDataStorageDefs.h"

#include <algorithm>

#include "Logger/Logger.h"
#include "common/Buffer.h"

namespace NS_DM_Client
{
namespace NS_DataStorage
{

//------------------------------------------------------------------------------------------------------

IStorageContent::IStorageContent(const String& name)
    : m_name(name)
{ }

//------------------------------------------------------------------------------------------------------

const String& IStorageContent::Name() const
{
    return m_name;
}

//------------------------------------------------------------------------------------------------------

LeafStorageContent::LeafStorageContent(const String& name, const void* value, size_t size)
    : IStorageContent(name), m_value(0), m_size(size)
{ 
    if (!((value == 0) || (m_size <= 0)))
    {
        m_value = malloc(m_size);
        if(m_value == NULL)
        {
            LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog),"malloc m_value");
            return;
        }
        memset(m_value, 0, m_size);
        memcpy(m_value, value, m_size);
    }
}

//------------------------------------------------------------------------------------------------------

LeafStorageContent::~LeafStorageContent()
{ 
    if (m_value)
    {
        free(m_value);
    }
}
    
//------------------------------------------------------------------------------------------------------

IStorageContent* LeafStorageContent::Clone()
{
    return (new(std::nothrow) LeafStorageContent(m_name, m_value, m_size));
}

//------------------------------------------------------------------------------------------------------

bool LeafStorageContent::GetValue(void*& value, size_t& size) 
{ 
    value = m_value;
    size = m_size;
    return true;
} 

//------------------------------------------------------------------------------------------------------

bool LeafStorageContent::GetSize(size_t& size)
{
    size = m_size;
    return true;
}

//------------------------------------------------------------------------------------------------------

bool LeafStorageContent::SetValue(const void* value, size_t size) 
{
    if (m_value)
    {
        free(m_value);
        m_value = 0;
        m_size = 0;
    }
    
    if (!((value == 0) || (m_size <= 0)))
    {
        m_size = size;
        m_value = malloc(m_size);
        if(m_value == NULL)
        {
            LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog),"malloc m_value");
            return false;
        }
        memset(m_value, 0, m_size);
        memcpy(m_value, value, m_size);
    }

    return true;
} 

//------------------------------------------------------------------------------------------------------

DirectoryStorageContent::DirectoryStorageContent(const String& name)
    : IStorageContent(name)
{ 
    m_current = m_unders.end();
}

//------------------------------------------------------------------------------------------------------

DirectoryStorageContent::~DirectoryStorageContent()
{
    for (Unders::iterator iter = m_unders.begin(); iter != m_unders.end(); ++iter)
    {
        delete (*iter);
    }
}

//------------------------------------------------------------------------------------------------------

IStorageContent* DirectoryStorageContent::Clone()
{
    IStorageContent* clon = new(std::nothrow) DirectoryStorageContent(m_name);
    if(clon == NULL) LOG_WARNING_(NS_Logging::GetLogger(c_DataStorageLog),"new DirectoryStorageContent");

    for (Unders::iterator iter = m_unders.begin(); iter != m_unders.end(); ++iter)
    {
        clon->AddUnder((*iter)->Clone());
    }
    return clon;
}

//------------------------------------------------------------------------------------------------------
    
IStorageContent* DirectoryStorageContent::GetFirstChildren()
{
    for (m_current = m_unders.begin(); m_current != m_unders.end(); ++m_current)
    {
        if (!((*m_current)->IsLeaf()))
        {
            return (*m_current);
        }
    }
    return 0;
}

//------------------------------------------------------------------------------------------------------

IStorageContent* DirectoryStorageContent::GetNextChildren()
{
    for (++m_current; m_current != m_unders.end(); ++m_current)
    {
        if (!((*m_current)->IsLeaf()))
        {
            return (*m_current);
        }
    }
    StopGetChildren();
    return 0;
}

//------------------------------------------------------------------------------------------------------

void DirectoryStorageContent::StopGetChildren()
{
    m_current = m_unders.end();
}

//------------------------------------------------------------------------------------------------------

IStorageContent* DirectoryStorageContent::GetUnderByName(const String& name)
{
    for (Unders::iterator iter = m_unders.begin(); iter != m_unders.end(); ++iter)
    {
        if ((*iter)->Name().compare(name) == 0)
        {
            return (*iter);
        }
    }
    return 0;
}

//------------------------------------------------------------------------------------------------------

bool DirectoryStorageContent::AddUnder(IStorageContent* children)
{
    if (children)
    {
        m_unders.push_back(children);   
        return true;
    }
    return false;
}

//------------------------------------------------------------------------------------------------------

bool DirectoryStorageContent::DeleteUnder(const String& name)
{
    for (Unders::iterator iter = m_unders.begin(); iter != m_unders.end(); ++iter)
    {
        if ((*iter)->Name().compare(name) == 0)
        {
            delete (*iter);
            m_unders.erase(iter); // TODO optimize with remove(erase)
            return true;
        }
    }
    return false;
}

//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------

CMemoryDataStorage::CMemoryDataStorage(const String& profile) : m_base_path(""), m_content(0)
{   // profile - no need profile in memory realization
}

//------------------------------------------------------------------------------------------------------

bool CMemoryDataStorage::Init(const String& base_path)
{   // base path need only for GetBasePath() member method

    m_base_path = base_path.empty() ? String(c_privateDataPath) : base_path;
    return loadInitialTree();
}

//------------------------------------------------------------------------------------------------------

void CMemoryDataStorage::Release()
{
    delete m_content;
    delete this;
}

//------------------------------------------------------------------------------------------------------

IStreamHandler* CMemoryDataStorage::CreateStream()
{
    return 0;
}

//------------------------------------------------------------------------------------------------------

bool CMemoryDataStorage::SavePrivateData(const String& key, const void* buffer, size_t size, bool profileSpecific)
{
    bool res = ((key.length() > 0));
    if (res)
    {
        if (createPrivateDataPath(key.c_str(), profileSpecific))
        {
            if (!(res = savePrivateData(key.c_str(), buffer, size)))
            {
                LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "save private data to memory is failed. key: %s", key.c_str());
            }
        }
        else
        {
            LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "can't create directories in memory from key path");
        }
    }
    else
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "key lenght, input buffer or buffer size = 0. key: %s", key.c_str());
    }
    return res;
}

//------------------------------------------------------------------------------------------------------

bool CMemoryDataStorage::SavePrivateData(const String& key, const Buffer& buffer, bool profileSpecific)
{
    return SavePrivateData(key, buffer.GetPointer(), buffer.Size(), profileSpecific);
}

//------------------------------------------------------------------------------------------------------

bool CMemoryDataStorage::LoadPrivateData(const String& key, Buffer& buffer, bool profileSpecific)
{
    bool res = (key.length() > 0);
    if (res)
    {
        void* tmpbuff = 0;
        size_t sizebuff = 0;

        if((res = loadPrivateData(key.c_str(), tmpbuff, sizebuff)) == true)
        {
            if (sizebuff == 0)
            {
                buffer.Allocate(0);
            }
            else
            {
                if ((res = buffer.Allocate(sizebuff)))
                {
                    memcpy(buffer.GetPointer(), tmpbuff, sizebuff);
                }
                else
                {
                    LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "can't allocate buffer. key: %s", key.c_str());
                }
                free(tmpbuff);
            }
        }
    }
    else
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "key lenght = 0. key: %s", key.c_str());
    }
    return res;
}

//------------------------------------------------------------------------------------------------------

bool CMemoryDataStorage::GetChildList(const String& key, StringArray& list, bool profileSpecific)
{
    bool res = (key.length() > 0);
    if (res)
    {   
        IStorageContent* key_node = getNodeByFullKeyPath(key.c_str());
        if (key_node && (!key_node->IsLeaf()))
        {
            res = true;             
            IStorageContent* current = key_node->GetFirstChildren();
            while (current)
            {
                list.push_back(current->Name());
                current = key_node->GetNextChildren();
            }
            key_node->StopGetChildren();
        }
        else
        {
            LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "can't get node by path. key: %s", key.c_str());
            res = false;
        }
    }
    else
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "key lenght = 0. key: %s", key.c_str());
    }

    if (res)
    {
        std::sort(list.begin(), list.end());
    }

    return res;
}

//------------------------------------------------------------------------------------------------------

bool CMemoryDataStorage::Exist(const String& key, bool profileSpecific)
{
    bool res = (key.length() > 0);
    if (res)
    {
        IStorageContent* key_node = getNodeByFullKeyPath(key.c_str());
        res = (key_node && (!key_node->IsLeaf())) ? true : false;
    }
    else
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "key lenght = 0. key: %s", key.c_str());
    }
    return res;
}

//------------------------------------------------------------------------------------------------------

bool CMemoryDataStorage::RemovePrivateData(const String& key)
{
    bool res = (key.length() > 0);
    if (res)
    {
        IStorageContent* key_node = getParentNodeOfKeyByFullKeyPath(key.c_str());
        if (key_node)
        {
            res = key_node->DeleteUnder(getKeyNameFromPath(key.c_str()));
        }
        else
        {
            LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "can't get parent node of key. key: %s", key.c_str());
            res = false;
        }
    }
    else
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "key lenght = 0. key: %s", key.c_str());
    }
    return res;
}
//------------------------------------------------------------------------------------------------------

IStorageContent* CMemoryDataStorage::getParentNodeOfKeyByFullKeyPath(const char* key)
{
    String Key = key;
    size_t pos_beg = 0;
    size_t pos_end = 0;
    String dir_name;

    IStorageContent* current = m_content;
    IStorageContent* under = 0;
    
    while ( (pos_end = Key.find(c_pathSeparatorStr, pos_beg)) != String::npos )
    {
        dir_name = Key.substr(pos_beg, pos_end - pos_beg);
        if (m_content->Name().compare(dir_name) != 0)
        {
            under = current->GetUnderByName(dir_name);
            if (under && (!under->IsLeaf())) 
            {   // directory sub-path exist
                current = under;
            }
            else 
            {   // directory sub-path not exist. Error
                return 0;
            }
        }
        pos_beg = pos_end + 1;
    }

    return current;
}

//------------------------------------------------------------------------------------------------------

const char* CMemoryDataStorage::getKeyNameFromPath(const char* key)
{
    const char* res = key + strlen(key);
    while (*(--res) != '/')
    {
        if (res == key)
        {   
            return 0;
        }
    }
    return ++res;
}

//------------------------------------------------------------------------------------------------------

bool CMemoryDataStorage::savePrivateData(const char* key, const void* buffer, size_t size)
{
    bool res = false;

    IStorageContent* directory = getParentNodeOfKeyByFullKeyPath(key);
    if (directory)
    {
        IStorageContent* leaf_node = new(std::nothrow) LeafStorageContent(getKeyNameFromPath(key), buffer, size);
        if (leaf_node)
        {
            res = directory->AddUnder(leaf_node);
        }
        else
        {
            LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "failed to create leaf node for key. key: %s", key);
        }
    }
    else
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "can't get parent node of key. key: %s", key);
    }

    return res;
}

//------------------------------------------------------------------------------------------------------

bool CMemoryDataStorage::loadPrivateData(const char* key, void*& buffer, size_t& size)
{
    bool res = false;

    if (readBufferSize(key, size))
    {
        if (size == 0)
        {
            res = true;
        }
        else
        {
            IStorageContent* leaf_node = getLeafNodeByFullKeyPath(key);
            if (leaf_node)
            {
                void* content = 0;
                if (leaf_node->GetValue(content, size))
                {
                    if ((buffer = malloc(size)) != 0)
                    {
                        memset(buffer, 0, size);
                        memcpy(buffer, content, size);
                        res = true;
                    }
                    else
                    {
                        LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "can't allocate buffer. key : %s", key);
                    }
                }
                else
                {
                    LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "can't get value of leaf node of key. key: %s", key);
                }
            }
            else
            {
                LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "can't get leaf node of key. key: %s", key);
            }
        }
    }
    else
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "failed to read buffer size. key : %s", key);
    }

    return res;
}

//------------------------------------------------------------------------------------------------------

IStorageContent* CMemoryDataStorage::getNodeByFullKeyPath(const char* key)
{   
    IStorageContent* parent_node = getParentNodeOfKeyByFullKeyPath(key);
    if (parent_node)
    {
        IStorageContent* key_node = parent_node->GetUnderByName(getKeyNameFromPath(key));
        if (key_node)
        {
            return key_node;
        }
    }
    return 0;
}

//------------------------------------------------------------------------------------------------------

IStorageContent* CMemoryDataStorage::getLeafNodeByFullKeyPath(const char* key)
{
    IStorageContent* key_node = getNodeByFullKeyPath(key);
    if (key_node && key_node->IsLeaf())
    {
        return key_node;
    }
    return 0;
}

//------------------------------------------------------------------------------------------------------

bool CMemoryDataStorage::readBufferSize(const char* key, size_t& size)
{
    IStorageContent* leaf_node = getLeafNodeByFullKeyPath(key);
    if (leaf_node)
    {
        return leaf_node->GetSize(size);
    }
    else
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_DataStorageLog), "can't get leaf node of key. key: %s", key);
    }

    return false;
}

//------------------------------------------------------------------------------------------------------

bool CMemoryDataStorage::createPrivateDataPath(const char* key, bool profileSpecific)
{
    String Key = key;
    size_t pos_beg = 0;
    size_t pos_end = 0;
    String dir_name;
    
    IStorageContent* current = m_content;
    IStorageContent* under = 0;
    IStorageContent* directory = 0;
    while ( (pos_end = Key.find(c_pathSeparatorStr, pos_beg)) != String::npos )
    {
        dir_name = Key.substr(pos_beg, pos_end - pos_beg);
        if (m_content->Name().compare(dir_name) != 0)
        {
            under = current->GetUnderByName(dir_name);
            if (under && (!under->IsLeaf())) 
            {   // directory already exist
                current = under;
            }
            else if (under && under->IsLeaf())
            {   // node already exist but not directory. Error
                return false;
            }
            else if (!under)
            {   // directory not exist. Create
                directory = new(std::nothrow) DirectoryStorageContent(dir_name); 
                if (directory)
                {
                    if (current->AddUnder(directory))
                    {
                        current = directory;
                    }
                    else
                    {
                        delete directory;
                        return false;
                    }
                }
                else
                {
                    LOG_WARNING_(NS_Logging::GetLogger(c_DataStorageLog), "new DirectoryStorageContent");
                }
            }
        }
        pos_beg = pos_end + 1;
    }
    return true;
}

//------------------------------------------------------------------------------------------------------

const char* CMemoryDataStorage::GetBasePath()
{
    return m_base_path.c_str();
}

//------------------------------------------------------------------------------------------------------

bool CMemoryDataStorage::GetPrivateDataSize(const String& key, size_t& size, bool profileSpecific)
{
    return readBufferSize(key.c_str(), size);
}

//------------------------------------------------------------------------------------------------------

bool CMemoryDataStorage::loadInitialTree()
{
    /*
    IStorageContent* DMAcc_0_AppAddr_moon_Addr_node = new DirectoryStorageContent("Addr");
    DMAcc_0_AppAddr_moon_Addr_node->AddUnder(new LeafStorageContent("ACL", "", 0));
    DMAcc_0_AppAddr_moon_Addr_node->AddUnder(new LeafStorageContent("Format", "chr", 3));
    DMAcc_0_AppAddr_moon_Addr_node->AddUnder(new LeafStorageContent("Type", "text/plain", 10));
    DMAcc_0_AppAddr_moon_Addr_node->AddUnder(new LeafStorageContent("content", "http://idovgaliuk-pc:8080/funambol/dm", 37));

    IStorageContent* DMAcc_0_AppAddr_moon_AddrType_node = new DirectoryStorageContent("AddrType");
    DMAcc_0_AppAddr_moon_Addr_node->AddUnder(new LeafStorageContent("ACL", "", 0));
    DMAcc_0_AppAddr_moon_Addr_node->AddUnder(new LeafStorageContent("Format", "chr", 3));
    DMAcc_0_AppAddr_moon_Addr_node->AddUnder(new LeafStorageContent("Type", "text/plain", 10));
    DMAcc_0_AppAddr_moon_Addr_node->AddUnder(new LeafStorageContent("content", "URI", 3));

    IStorageContent* DMAcc_0_AppAddr_moon_node = new DirectoryStorageContent("moon");
    DMAcc_0_AppAddr_moon_node->AddUnder(new LeafStorageContent("ACL", "", 0));
    DMAcc_0_AppAddr_moon_node->AddUnder(new LeafStorageContent("Format", "node", 4));
    DMAcc_0_AppAddr_moon_node->AddUnder(new LeafStorageContent("Type", "node", 4));
    DMAcc_node->AddUnder(DMAcc_0_AppAddr_moon_Addr_node);
    DMAcc_node->AddUnder(DMAcc_0_AppAddr_moon_AddrType_node);
    
*/
    IStorageContent* DMAcc_bomba_node = new(std::nothrow) DirectoryStorageContent("0");
    DMAcc_bomba_node->AddUnder(new(std::nothrow) LeafStorageContent("ACL", "", 0));
    DMAcc_bomba_node->AddUnder(new(std::nothrow) LeafStorageContent("Format", "node", 4));
    DMAcc_bomba_node->AddUnder(new(std::nothrow) LeafStorageContent("Type", "node", 4));

    IStorageContent* DMAcc_node = new(std::nothrow) DirectoryStorageContent("DMAcc");
    DMAcc_node->AddUnder(new(std::nothrow) LeafStorageContent("ACL", "", 0));
    DMAcc_node->AddUnder(new(std::nothrow) LeafStorageContent("Format", "node", 4));
    DMAcc_node->AddUnder(new(std::nothrow) LeafStorageContent("Type", "node", 4));
    DMAcc_node->AddUnder(new(std::nothrow) LeafStorageContent("permanent", "true", 4));
    DMAcc_node->AddUnder(DMAcc_bomba_node);

    IStorageContent* DevDetail_node = new(std::nothrow) DirectoryStorageContent("DevDetail");
    DevDetail_node->AddUnder(new(std::nothrow) LeafStorageContent("ACL", "Get=*", 5));
    DevDetail_node->AddUnder(new(std::nothrow) LeafStorageContent("Format", "node", 4));
    DevDetail_node->AddUnder(new(std::nothrow) LeafStorageContent("Type", "node", 4));
    DevDetail_node->AddUnder(new(std::nothrow) LeafStorageContent("permanent", "true", 4));
    
    IStorageContent* DevInfo_node = new(std::nothrow) DirectoryStorageContent("DevInfo");
    DevInfo_node->AddUnder(new(std::nothrow) LeafStorageContent("ACL", "Get=*", 5));
    DevInfo_node->AddUnder(new(std::nothrow) LeafStorageContent("Format", "node", 4));
    DevInfo_node->AddUnder(new(std::nothrow) LeafStorageContent("Type", "node", 4));
    DevInfo_node->AddUnder(new(std::nothrow) LeafStorageContent("permanent", "true", 4));
    
    IStorageContent* WiMAX_node = new(std::nothrow) DirectoryStorageContent("WiMAX");
    WiMAX_node->AddUnder(new(std::nothrow) LeafStorageContent("ACL", "", 0));
    WiMAX_node->AddUnder(new(std::nothrow) LeafStorageContent("Format", "node", 4));
    WiMAX_node->AddUnder(new(std::nothrow) LeafStorageContent("Type", "node", 4));
    WiMAX_node->AddUnder(new(std::nothrow) LeafStorageContent("permanent", "true", 4));
    
    IStorageContent* WiMAX_Diagnostics_Generic_node = new(std::nothrow) DirectoryStorageContent("Generic");
    WiMAX_Diagnostics_Generic_node->AddUnder(new(std::nothrow) LeafStorageContent("ACL", "Get=*", 5));
    WiMAX_Diagnostics_Generic_node->AddUnder(new(std::nothrow) LeafStorageContent("Format", "node", 4));
    WiMAX_Diagnostics_Generic_node->AddUnder(new(std::nothrow) LeafStorageContent("Type", "node", 4));
    WiMAX_Diagnostics_Generic_node->AddUnder(new(std::nothrow) LeafStorageContent("permanent", "true", 4));
    
    IStorageContent* WiMAX_Diagnostics_Start_node = new(std::nothrow) DirectoryStorageContent("Start");
    WiMAX_Diagnostics_Start_node->AddUnder(new(std::nothrow) LeafStorageContent("ACL", "Exec=*", 6));
    WiMAX_Diagnostics_Start_node->AddUnder(new(std::nothrow) LeafStorageContent("Format", "node", 4));
    WiMAX_Diagnostics_Start_node->AddUnder(new(std::nothrow) LeafStorageContent("Type", "node", 4));
    WiMAX_Diagnostics_Start_node->AddUnder(new(std::nothrow) LeafStorageContent("permanent", "true", 4));

    IStorageContent* WiMAX_Diagnostics_WiMAX_node = new(std::nothrow) DirectoryStorageContent("WiMAX");
    WiMAX_Diagnostics_WiMAX_node->AddUnder(new(std::nothrow) LeafStorageContent("ACL", "Get=*", 5));
    WiMAX_Diagnostics_WiMAX_node->AddUnder(new(std::nothrow) LeafStorageContent("Format", "node", 4));
    WiMAX_Diagnostics_WiMAX_node->AddUnder(new(std::nothrow) LeafStorageContent("Type", "node", 4));
    WiMAX_Diagnostics_WiMAX_node->AddUnder(new(std::nothrow) LeafStorageContent("permanent", "true", 4));

    IStorageContent* WiMAX_Diagnostics_node = new(std::nothrow) DirectoryStorageContent("WiMAX_Diagnostics");
    WiMAX_Diagnostics_node->AddUnder(new(std::nothrow) LeafStorageContent("ACL", "Get=*", 5));
    WiMAX_Diagnostics_node->AddUnder(new(std::nothrow) LeafStorageContent("Format", "node", 4));
    WiMAX_Diagnostics_node->AddUnder(new(std::nothrow) LeafStorageContent("Type", "node", 4));
    WiMAX_Diagnostics_node->AddUnder(new(std::nothrow) LeafStorageContent("permanent", "true", 4));
    WiMAX_Diagnostics_node->AddUnder(WiMAX_Diagnostics_Generic_node);
    WiMAX_Diagnostics_node->AddUnder(WiMAX_Diagnostics_Start_node);
    WiMAX_Diagnostics_node->AddUnder(WiMAX_Diagnostics_WiMAX_node);

    IStorageContent* root_node = new(std::nothrow) DirectoryStorageContent(c_root_key);
    root_node->AddUnder(new(std::nothrow) LeafStorageContent("ACL", "Add=*&Get=*", 11));
    root_node->AddUnder(new(std::nothrow) LeafStorageContent("Format", "node", 4));
    root_node->AddUnder(new(std::nothrow) LeafStorageContent("Type", "node", 4));
    root_node->AddUnder(new(std::nothrow) LeafStorageContent("permanent", "true", 4));
    root_node->AddUnder(DMAcc_node);
    root_node->AddUnder(DevDetail_node);
    root_node->AddUnder(DevInfo_node);
    root_node->AddUnder(WiMAX_node);
    root_node->AddUnder(WiMAX_Diagnostics_node);

    m_content = root_node;
    return true;
}

//------------------------------------------------------------------------------------------------------

}
}
