2000-11-07 07:35:59 -06:00
|
|
|
/*************************************************************************
|
|
|
|
*
|
|
|
|
* $RCSfile: treeimpl.cxx,v $
|
|
|
|
*
|
2001-06-21 06:02:38 -05:00
|
|
|
* $Revision: 1.18 $
|
2000-11-07 07:35:59 -06:00
|
|
|
*
|
2001-06-21 06:02:38 -05:00
|
|
|
* last change: $Author: jb $ $Date: 2001-06-21 12:02:38 $
|
2000-11-07 07:35:59 -06:00
|
|
|
*
|
|
|
|
* The Contents of this file are made available subject to the terms of
|
|
|
|
* either of the following licenses
|
|
|
|
*
|
|
|
|
* - GNU Lesser General Public License Version 2.1
|
|
|
|
* - Sun Industry Standards Source License Version 1.1
|
|
|
|
*
|
|
|
|
* Sun Microsystems Inc., October, 2000
|
|
|
|
*
|
|
|
|
* GNU Lesser General Public License Version 2.1
|
|
|
|
* =============================================
|
|
|
|
* Copyright 2000 by Sun Microsystems, Inc.
|
|
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
|
|
* MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Sun Industry Standards Source License Version 1.1
|
|
|
|
* =================================================
|
|
|
|
* The contents of this file are subject to the Sun Industry Standards
|
|
|
|
* Source License Version 1.1 (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.openoffice.org/license.html.
|
|
|
|
*
|
|
|
|
* Software provided under this License is provided on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
|
|
|
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
|
|
|
|
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
|
|
|
|
* See the License for the specific provisions governing your rights and
|
|
|
|
* obligations concerning the Software.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
|
|
|
|
*
|
|
|
|
* Copyright: 2000 by Sun Microsystems, Inc.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s): _______________________________________
|
|
|
|
*
|
|
|
|
*
|
|
|
|
************************************************************************/
|
2000-11-13 04:54:51 -06:00
|
|
|
#include <stdio.h>
|
2000-11-07 07:35:59 -06:00
|
|
|
#include "treeimpl.hxx"
|
|
|
|
#include "roottreeimpl.hxx"
|
|
|
|
|
|
|
|
#include "nodeimpl.hxx"
|
|
|
|
#include "nodechangeimpl.hxx"
|
|
|
|
#include "template.hxx"
|
|
|
|
|
2000-11-19 18:38:19 -06:00
|
|
|
#include "valuenode.hxx"
|
|
|
|
#include "change.hxx"
|
2000-11-07 07:35:59 -06:00
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
#include "valuenodeimpl.hxx"
|
|
|
|
#include "setnodeimplbase.hxx"
|
|
|
|
#include "groupnodeimpl.hxx"
|
2000-11-19 20:11:02 -06:00
|
|
|
|
|
|
|
#include <algorithm> // for reverse
|
2000-11-07 07:35:59 -06:00
|
|
|
#include <osl/diagnose.h>
|
|
|
|
|
|
|
|
namespace configmgr
|
|
|
|
{
|
|
|
|
namespace configuration
|
|
|
|
{
|
|
|
|
|
2001-02-23 03:50:59 -06:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline
|
|
|
|
static
|
|
|
|
Name nodeName(INode const& aNode)
|
|
|
|
{
|
|
|
|
return Name(aNode.getName(),Name::NoValidate());
|
|
|
|
}
|
2000-11-07 07:35:59 -06:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// class TreeImplBuilder - friend of TreeImpl
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/** is a visitor-style algorithm to construct a <type>TreeImpl::NodeList</type>
|
|
|
|
representing a configuration hierarchy
|
|
|
|
*/
|
|
|
|
class TreeImplBuilder : public NodeModification
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** constructs a TreeImplBuilder to append onto <var>rList</var>
|
|
|
|
the products of <var>rFactory</var> up to depth <var>nDepth</var>
|
|
|
|
*/
|
2000-11-19 18:38:19 -06:00
|
|
|
TreeImplBuilder(TemplateProvider const& aTemplateProvider, NodeFactory& rFactory, TreeImpl& rTree)
|
|
|
|
: m_aTemplateProvider(aTemplateProvider)
|
|
|
|
, m_rFactory(rFactory)
|
2000-11-07 07:35:59 -06:00
|
|
|
, m_rTree(rTree)
|
|
|
|
, m_nParent(0)
|
|
|
|
, m_nDepthLeft(rTree.m_nDepth)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(m_rTree.m_aNodes.empty());
|
2001-06-20 14:44:49 -05:00
|
|
|
OSL_DEBUG_ONLY(m_bMemberCheck = false);
|
2000-11-07 07:35:59 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
/// implements the NodeModification handler for ValueNodes
|
|
|
|
virtual void handle(ValueNode& rValue);
|
|
|
|
/// implements the NodeModification member for ValueNodes
|
|
|
|
virtual void handle(ISubtree& rTree);
|
|
|
|
|
|
|
|
/// add a Node for group node <var>rGroup</var> to the list
|
|
|
|
void addGroup(ISubtree& rGroup);
|
|
|
|
/// add a Node for set node <var>rSet</var> to the list
|
|
|
|
void addSet(ISubtree& rSet);
|
|
|
|
/// add a Node for value node <var>rValue</var> to the list
|
2001-06-20 14:44:49 -05:00
|
|
|
void addValueElement(ValueNode& rValue);
|
|
|
|
/// add a Member for value node <var>rValue</var> to the list
|
|
|
|
void addValueMember(ValueNode& rValue);
|
2000-11-07 07:35:59 -06:00
|
|
|
|
2000-11-19 18:38:19 -06:00
|
|
|
TemplateProvider m_aTemplateProvider;
|
2000-11-07 07:35:59 -06:00
|
|
|
NodeFactory& m_rFactory;
|
2001-06-20 14:44:49 -05:00
|
|
|
TreeImpl& m_rTree;
|
|
|
|
NodeOffset m_nParent;
|
|
|
|
TreeDepth m_nDepthLeft;
|
|
|
|
#ifdef _DEBUG
|
|
|
|
bool m_bMemberCheck;
|
|
|
|
#endif
|
2000-11-07 07:35:59 -06:00
|
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TreeImplBuilder::handle(ValueNode& rValue)
|
|
|
|
{
|
2001-06-20 14:44:49 -05:00
|
|
|
if (m_nParent == 0)
|
|
|
|
addValueElement(rValue); // if it is the root it is a value set element
|
|
|
|
else
|
|
|
|
addValueMember(rValue); // if it is not the root it is a group member
|
2000-11-07 07:35:59 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TreeImplBuilder::handle(ISubtree& rTree)
|
|
|
|
{
|
|
|
|
if (rTree.isSetNode())
|
|
|
|
addSet(rTree);
|
|
|
|
else
|
|
|
|
addGroup(rTree);
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
void TreeImplBuilder::addValueElement(ValueNode& rValue)
|
2000-11-07 07:35:59 -06:00
|
|
|
{
|
|
|
|
NodeImplHolder aValueNode( m_rFactory.makeValueNode(rValue) );
|
|
|
|
OSL_ENSURE( aValueNode.isValid(), "could not make value node wrapper" );
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
OSL_ENSURE( m_nParent == 0, "Adding value element that is not root of its fragment" );
|
2000-11-07 07:35:59 -06:00
|
|
|
// TODO:!isValid() => maybe substitute a SimpleValueNodeImpl if possible
|
|
|
|
if( aValueNode.isValid() )
|
|
|
|
{
|
2001-02-23 03:50:59 -06:00
|
|
|
m_rTree.m_aNodes.push_back( Node(aValueNode,nodeName(rValue),m_nParent) );
|
2000-11-07 07:35:59 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
void TreeImplBuilder::addValueMember(ValueNode& )
|
|
|
|
{
|
|
|
|
// nothing to do
|
|
|
|
OSL_DEBUG_ONLY(m_bMemberCheck = true);
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2000-11-07 07:35:59 -06:00
|
|
|
void TreeImplBuilder::addGroup(ISubtree& rTree)
|
|
|
|
{
|
|
|
|
NodeImplHolder aGroupNode( m_rFactory.makeGroupNode(rTree) );
|
|
|
|
OSL_ENSURE( aGroupNode.isValid(), "could not make group node wrapper" );
|
|
|
|
|
|
|
|
// TODO:!isValid() => maybe substitute a SimpleValueNodeImpl if possible
|
|
|
|
if( aGroupNode.isValid() )
|
|
|
|
{
|
2001-02-23 03:50:59 -06:00
|
|
|
m_rTree.m_aNodes.push_back( Node(aGroupNode,nodeName(rTree),m_nParent) );
|
2000-11-07 07:35:59 -06:00
|
|
|
|
|
|
|
// now fill in group members
|
|
|
|
if (m_nDepthLeft > 0)
|
|
|
|
{
|
|
|
|
NodeOffset nSaveParent = m_nParent;
|
2000-11-14 03:53:36 -06:00
|
|
|
decDepth(m_nDepthLeft);
|
2000-11-07 07:35:59 -06:00
|
|
|
|
|
|
|
m_nParent = m_rTree.m_aNodes.size() + m_rTree.root() - 1;
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
#ifdef _DEBUG
|
|
|
|
bool bSaveMemberCheck = m_bMemberCheck;
|
|
|
|
m_bMemberCheck = false;
|
|
|
|
#endif
|
|
|
|
|
2000-11-07 07:35:59 -06:00
|
|
|
// now recurse:
|
|
|
|
this->applyToChildren(rTree);
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
OSL_ENSURE(m_nParent < m_rTree.m_aNodes.size() || m_bMemberCheck,
|
|
|
|
"WARNING: Configuration: Group within requested depth has no members");
|
|
|
|
|
|
|
|
OSL_DEBUG_ONLY(m_bMemberCheck = bSaveMemberCheck);
|
|
|
|
|
2000-11-14 03:53:36 -06:00
|
|
|
incDepth(m_nDepthLeft);
|
2000-11-07 07:35:59 -06:00
|
|
|
m_nParent = nSaveParent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TreeImplBuilder::addSet(ISubtree& rTree)
|
|
|
|
{
|
2000-11-19 18:38:19 -06:00
|
|
|
TemplateHolder aTemplate = makeSetElementTemplate(rTree, m_aTemplateProvider);
|
2000-11-07 07:35:59 -06:00
|
|
|
OSL_ASSERT(aTemplate.isValid());
|
2000-11-19 18:38:19 -06:00
|
|
|
OSL_ENSURE(aTemplate->isInstanceTypeKnown(),"ERROR: Cannor create set instance without knowing the instance type");
|
2000-11-07 07:35:59 -06:00
|
|
|
|
|
|
|
NodeImplHolder aSetNode( m_rFactory.makeSetNode(rTree,aTemplate.getBodyPtr()) );
|
|
|
|
OSL_ENSURE( aSetNode.isValid(), "could not make set node wrapper" );
|
|
|
|
|
|
|
|
// TODO:!isValid() => maybe substitute a SimpleValueNodeImpl if possible
|
|
|
|
if( aSetNode.isValid() )
|
|
|
|
{
|
2001-02-23 03:50:59 -06:00
|
|
|
m_rTree.m_aNodes.push_back( Node(aSetNode,nodeName(rTree),m_nParent) );
|
2000-11-07 07:35:59 -06:00
|
|
|
|
|
|
|
// this also relies on one based offsets
|
|
|
|
NodeOffset nNodeAdded = m_rTree.m_aNodes.size() + m_rTree.root() - 1;
|
|
|
|
|
2000-11-19 18:38:19 -06:00
|
|
|
m_rTree.m_aNodes.back().setImpl().initElements(m_aTemplateProvider, m_rTree, nNodeAdded, m_nDepthLeft);
|
2000-11-07 07:35:59 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// class Node
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-02-23 03:50:59 -06:00
|
|
|
Node::Node(NodeImplHolder const& aSpecificNode, Name const& aName, NodeOffset nParent)
|
2000-11-07 07:35:59 -06:00
|
|
|
: m_pSpecificNode(aSpecificNode)
|
|
|
|
, m_nParent(nParent)
|
2001-02-23 03:50:59 -06:00
|
|
|
, m_aName(aName)
|
2000-11-07 07:35:59 -06:00
|
|
|
{
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// class TreeImpl
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/// creates a TreeImpl for a detached, virgin instance of <var>aTemplate</var>
|
2000-11-19 18:38:19 -06:00
|
|
|
TreeImpl::TreeImpl( )
|
2000-11-07 07:35:59 -06:00
|
|
|
: m_aNodes()
|
|
|
|
, m_pParentTree(0)
|
|
|
|
, m_nParentNode(0)
|
|
|
|
, m_nDepth(0)
|
2000-11-19 18:38:19 -06:00
|
|
|
//, m_nRoot(nRoot)
|
2000-11-07 07:35:59 -06:00
|
|
|
{
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
TreeImpl::TreeImpl( TreeImpl& rParentTree, NodeOffset nParentNode )
|
|
|
|
: m_aNodes()
|
|
|
|
, m_pParentTree(&rParentTree)
|
|
|
|
, m_nParentNode(nParentNode)
|
|
|
|
, m_nDepth(0)
|
2000-11-19 18:38:19 -06:00
|
|
|
//, m_nRoot(1)
|
2000-11-07 07:35:59 -06:00
|
|
|
{
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
TreeImpl::~TreeImpl()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2000-12-04 02:10:21 -06:00
|
|
|
void TreeImpl::disposeData()
|
|
|
|
{
|
|
|
|
m_aNodes.clear();
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2000-11-13 11:00:16 -06:00
|
|
|
void ElementTreeImpl::doGetPathRoot(Path::Components& rPath) const
|
|
|
|
{
|
|
|
|
rPath = AbsolutePath::detachedRoot().components();
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void RootTreeImpl::doGetPathRoot(Path::Components& rPath) const
|
|
|
|
{
|
|
|
|
rPath = m_aContextPath.components();
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void TreeImpl::implGetContextPath(Path::Components& rPath) const
|
2000-11-07 07:35:59 -06:00
|
|
|
{
|
2000-11-13 11:00:16 -06:00
|
|
|
if (m_pParentTree)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(m_nParentNode);
|
|
|
|
m_pParentTree->implGetContextPath(rPath);
|
|
|
|
m_pParentTree->appendPathTo(m_nParentNode,rPath);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
doGetPathRoot(rPath);
|
2000-11-07 07:35:59 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2000-11-13 11:00:16 -06:00
|
|
|
AbsolutePath TreeImpl::getContextPath() const
|
|
|
|
{
|
|
|
|
Path::Components aPath;
|
|
|
|
implGetContextPath(aPath);
|
|
|
|
return AbsolutePath(aPath);
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
2000-11-19 18:38:19 -06:00
|
|
|
void TreeImpl::build(NodeFactory& rFactory, INode& rCacheNode, TreeDepth nDepth, TemplateProvider const& aTemplateProvider)
|
2000-11-07 07:35:59 -06:00
|
|
|
{
|
|
|
|
OSL_ASSERT(m_aNodes.empty());
|
|
|
|
m_nDepth = nDepth;
|
2000-11-29 06:59:56 -06:00
|
|
|
TreeImplBuilder a(aTemplateProvider, rFactory,*this);
|
|
|
|
a.applyToNode(rCacheNode);
|
2000-11-07 07:35:59 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// context handling
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TreeImpl::setContext(TreeImpl* pParentTree, NodeOffset nParentNode)
|
|
|
|
{
|
|
|
|
OSL_ENSURE(pParentTree,"ERROR: Moving tree to nowhere");
|
|
|
|
|
|
|
|
if (pParentTree)
|
|
|
|
{
|
|
|
|
OSL_ENSURE( pParentTree->isValidNode(nParentNode),"ERROR: Moving tree to invalid node");
|
|
|
|
if (!pParentTree->isValidNode(nParentNode))
|
|
|
|
throw Exception("INTERNAL ERROR: Moving tree to invalid parent node");
|
|
|
|
|
|
|
|
OSL_ENSURE( pParentTree->node(nParentNode)->isSetNode(),"WARNING: Moving tree to node that is not a set");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OSL_ENSURE( nParentNode == 0,"WARNING: Moving tree to node without a tree");
|
|
|
|
nParentNode = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_pParentTree = pParentTree;
|
|
|
|
m_nParentNode = nParentNode;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TreeImpl::clearContext()
|
|
|
|
{
|
|
|
|
m_pParentTree = 0;
|
|
|
|
m_nParentNode = 0;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
bool TreeImpl::hasChanges() const
|
|
|
|
{
|
|
|
|
return node(root())->hasChanges();
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2000-11-19 18:38:19 -06:00
|
|
|
void TreeImpl::collectChanges(NodeChanges& rChanges)
|
2000-11-07 07:35:59 -06:00
|
|
|
{
|
|
|
|
implCollectChangesFrom(root(),rChanges);
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2000-11-19 18:38:19 -06:00
|
|
|
void TreeImpl::implCollectChangesFrom(NodeOffset nNode, NodeChanges& rChanges)
|
2000-11-07 07:35:59 -06:00
|
|
|
{
|
|
|
|
Node const* pNode = node(nNode);
|
|
|
|
if (pNode->hasChanges())
|
|
|
|
{
|
2000-11-19 18:38:19 -06:00
|
|
|
pNode->collectChanges(rChanges,this,nNode);
|
2000-11-07 07:35:59 -06:00
|
|
|
for (NodeOffset nChild = firstChild(nNode); isValidNode(nChild); nChild = findNextChild(nNode, nChild) )
|
|
|
|
{
|
|
|
|
implCollectChangesFrom(nChild,rChanges);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
2000-11-10 12:16:53 -06:00
|
|
|
// mark the given node and all its ancestors (we can stop when we hit a node that already is marked)
|
2000-11-07 07:35:59 -06:00
|
|
|
void TreeImpl::markChanged(NodeOffset nNode)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(isValidNode(nNode));
|
|
|
|
|
|
|
|
if (nNode)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Node* pNode = node(nNode);
|
|
|
|
pNode->markChanged();
|
|
|
|
|
|
|
|
nNode = pNode->parent();
|
|
|
|
}
|
2000-11-10 12:16:53 -06:00
|
|
|
while (nNode && !node(nNode)->hasChanges());
|
2000-11-07 07:35:59 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if (nNode == 0) // just marked parent
|
|
|
|
{
|
|
|
|
TreeImpl* pContext = getContextTree();
|
|
|
|
NodeOffset nContext = getContextNode();
|
|
|
|
if (pContext)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(pContext->isValidNode(nContext));
|
|
|
|
pContext->markChanged(nContext);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
void TreeImpl::commitDirect()
|
2000-11-07 07:35:59 -06:00
|
|
|
{
|
2001-06-20 14:44:49 -05:00
|
|
|
implCommitDirectFrom(root());
|
2000-11-07 07:35:59 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
void TreeImpl::implCommitDirectFrom(NodeOffset nNode)
|
2000-11-07 07:35:59 -06:00
|
|
|
{
|
|
|
|
Node* pNode = node(nNode);
|
|
|
|
if (pNode->hasChanges())
|
|
|
|
{
|
2001-06-20 14:44:49 -05:00
|
|
|
pNode->commitDirect();
|
2000-11-07 07:35:59 -06:00
|
|
|
for (NodeOffset nChild = firstChild(nNode); isValidNode(nChild); nChild = findNextChild(nNode, nChild) )
|
|
|
|
{
|
2001-06-20 14:44:49 -05:00
|
|
|
implCommitDirectFrom(nChild);
|
2000-11-07 07:35:59 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TreeImpl::makeIndirect(bool bIndirect)
|
|
|
|
{
|
|
|
|
// do it from outside in
|
|
|
|
for(NodeList::reverse_iterator it = m_aNodes.rbegin(), stop = m_aNodes.rend();
|
|
|
|
it != stop;
|
|
|
|
++it)
|
|
|
|
it->makeIndirect(bIndirect);
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2000-11-10 05:21:00 -06:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// old-style commit handling
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
std::auto_ptr<SubtreeChange> TreeImpl::preCommitChanges()
|
2000-11-10 05:21:00 -06:00
|
|
|
{
|
|
|
|
return doCommitChanges( root() );
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
void TreeImpl::finishCommit(SubtreeChange& rRootChange)
|
2000-11-10 05:21:00 -06:00
|
|
|
{
|
|
|
|
doFinishCommit( rRootChange, root() );
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
void TreeImpl::revertCommit(SubtreeChange& rRootChange)
|
2000-11-10 05:21:00 -06:00
|
|
|
{
|
|
|
|
doRevertCommit( rRootChange, root() );
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
void TreeImpl::recoverFailedCommit(SubtreeChange& rRootChange)
|
2000-12-07 07:48:18 -06:00
|
|
|
{
|
|
|
|
doFailedCommit( rRootChange, root() );
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
void TreeImpl::adjustToChanges(NodeChangesInformation& rLocalChanges, SubtreeChange const& aExternalChange)
|
2000-11-19 18:38:19 -06:00
|
|
|
{
|
2001-06-21 06:02:38 -05:00
|
|
|
OSL_PRECOND( getRootName().toString() == aExternalChange.getNodeName(), "Name of change does not match actual node" );
|
2000-11-19 18:38:19 -06:00
|
|
|
|
|
|
|
TreeDepth nDepth = getAvailableDepth();
|
|
|
|
|
2001-04-19 09:16:55 -05:00
|
|
|
doAdjustToChanges(rLocalChanges,aExternalChange,root(), nDepth);
|
2000-11-19 18:38:19 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
void TreeImpl::adjustToChanges(NodeChangesInformation& rLocalChanges, NodeOffset nNode, SubtreeChange const& aExternalChange)
|
2000-11-19 18:38:19 -06:00
|
|
|
{
|
|
|
|
OSL_PRECOND( isValidNode(nNode), "ERROR: Valid node required for adjusting to changes" );
|
2001-06-21 06:02:38 -05:00
|
|
|
OSL_PRECOND( getNodeName(nNode).toString() == aExternalChange.getNodeName(), "Name of change does not match actual node" );
|
2000-11-19 18:38:19 -06:00
|
|
|
|
|
|
|
TreeDepth nDepth = remainingDepth(getAvailableDepth(),depthTo(nNode));
|
|
|
|
|
2001-04-19 09:16:55 -05:00
|
|
|
doAdjustToChanges(rLocalChanges,aExternalChange,nNode, nDepth);
|
2000-11-19 18:38:19 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
std::auto_ptr<SubtreeChange> TreeImpl::doCommitChanges(NodeOffset nNode)
|
2000-11-10 05:21:00 -06:00
|
|
|
{
|
|
|
|
OSL_ASSERT(isValidNode(nNode));
|
|
|
|
Node* pNode = node(nNode);
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
std::auto_ptr<SubtreeChange> aRet;
|
2000-11-10 05:21:00 -06:00
|
|
|
|
|
|
|
if (!pNode->hasChanges())
|
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
OSL_ASSERT(!aRet.get());
|
|
|
|
OSL_ASSERT(nNode == root()); // only hit this for root (external request)
|
|
|
|
}
|
|
|
|
else if (pNode->isSetNode())
|
|
|
|
{
|
2001-06-20 14:44:49 -05:00
|
|
|
aRet = pNode->setImpl().preCommitChanges();
|
2000-11-10 05:21:00 -06:00
|
|
|
}
|
2001-06-20 14:44:49 -05:00
|
|
|
else if (pNode->isGroupNode())
|
2000-11-10 05:21:00 -06:00
|
|
|
{
|
|
|
|
std::auto_ptr<SubtreeChange> aGroupChange(pNode->groupImpl().preCommitChanges());
|
|
|
|
|
|
|
|
OSL_ASSERT(aGroupChange.get());
|
|
|
|
if (aGroupChange.get())
|
|
|
|
doCommitSubChanges( *aGroupChange, nNode);
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
aRet = aGroupChange;
|
2000-11-10 05:21:00 -06:00
|
|
|
}
|
2001-06-20 14:44:49 -05:00
|
|
|
else
|
|
|
|
OSL_ENSURE(nNode == root() && pNode->isValueElementNode(), "TreeImpl: Cannot commit changes: Unexpected node type");
|
|
|
|
|
2000-11-10 05:21:00 -06:00
|
|
|
return aRet;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
void TreeImpl::doFinishCommit(SubtreeChange& rSubtreeChange, NodeOffset nNode)
|
2000-11-10 05:21:00 -06:00
|
|
|
{
|
|
|
|
OSL_ASSERT(isValidNode(nNode));
|
|
|
|
Node* pNode = node(nNode);
|
|
|
|
|
2001-06-21 06:02:38 -05:00
|
|
|
OSL_ENSURE(rSubtreeChange.getNodeName() == getNodeName(nNode).toString(), "ERROR: Change name does not match node");
|
2001-06-20 14:44:49 -05:00
|
|
|
if (pNode->isSetNode())
|
2000-11-10 05:21:00 -06:00
|
|
|
{
|
|
|
|
OSL_ENSURE(rSubtreeChange.isSetNodeChange(),"ERROR: Change type GROUP does not match set");
|
|
|
|
|
|
|
|
pNode->setImpl().finishCommit(rSubtreeChange);
|
|
|
|
}
|
2001-06-20 14:44:49 -05:00
|
|
|
else if (pNode->isGroupNode())
|
2000-11-10 05:21:00 -06:00
|
|
|
{
|
|
|
|
OSL_ENSURE(!rSubtreeChange.isSetNodeChange(),"ERROR: Change type SET does not match group");
|
|
|
|
|
|
|
|
pNode->groupImpl().finishCommit(rSubtreeChange);
|
|
|
|
doFinishSubCommitted( rSubtreeChange, nNode);
|
|
|
|
}
|
2001-06-20 14:44:49 -05:00
|
|
|
else
|
|
|
|
OSL_ENSURE(nNode == root() && pNode->isValueElementNode(), "TreeImpl: Cannot finish commit: Unexpected node type");
|
2000-11-10 05:21:00 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
void TreeImpl::doRevertCommit(SubtreeChange& rSubtreeChange, NodeOffset nNode)
|
2000-11-10 05:21:00 -06:00
|
|
|
{
|
|
|
|
OSL_ASSERT(isValidNode(nNode));
|
|
|
|
Node* pNode = node(nNode);
|
|
|
|
|
2001-06-21 06:02:38 -05:00
|
|
|
OSL_ENSURE(rSubtreeChange.getNodeName() == getNodeName(nNode).toString(), "ERROR: Change name does not match node");
|
2001-06-20 14:44:49 -05:00
|
|
|
if (pNode->isSetNode())
|
2000-11-10 05:21:00 -06:00
|
|
|
{
|
|
|
|
OSL_ENSURE(rSubtreeChange.isSetNodeChange(),"ERROR: Change type GROUP does not match set");
|
|
|
|
|
|
|
|
pNode->setImpl().revertCommit(rSubtreeChange);
|
|
|
|
}
|
2001-06-20 14:44:49 -05:00
|
|
|
else if (pNode->isGroupNode())
|
2000-11-10 05:21:00 -06:00
|
|
|
{
|
|
|
|
OSL_ENSURE(!rSubtreeChange.isSetNodeChange(),"ERROR: Change type SET does not match group");
|
|
|
|
|
|
|
|
pNode->groupImpl().revertCommit(rSubtreeChange);
|
|
|
|
doRevertSubCommitted( rSubtreeChange, nNode);
|
|
|
|
}
|
2001-06-20 14:44:49 -05:00
|
|
|
else
|
|
|
|
OSL_ENSURE(nNode == root() && pNode->isValueElementNode(), "TreeImpl: Cannot revert commit: Unexpected node type");
|
2000-11-10 05:21:00 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
void TreeImpl::doFailedCommit(SubtreeChange& rSubtreeChange, NodeOffset nNode)
|
2000-12-07 07:48:18 -06:00
|
|
|
{
|
|
|
|
OSL_ASSERT(isValidNode(nNode));
|
|
|
|
Node* pNode = node(nNode);
|
|
|
|
|
2001-06-21 06:02:38 -05:00
|
|
|
OSL_ENSURE(rSubtreeChange.getNodeName() == getNodeName(nNode).toString(), "ERROR: Change name does not match node");
|
2001-06-20 14:44:49 -05:00
|
|
|
if (pNode->isSetNode())
|
2000-12-07 07:48:18 -06:00
|
|
|
{
|
|
|
|
OSL_ENSURE(rSubtreeChange.isSetNodeChange(),"ERROR: Change type GROUP does not match set");
|
|
|
|
|
|
|
|
pNode->setImpl().failedCommit(rSubtreeChange);
|
|
|
|
}
|
2001-06-20 14:44:49 -05:00
|
|
|
else if (pNode->isGroupNode())
|
2000-12-07 07:48:18 -06:00
|
|
|
{
|
|
|
|
OSL_ENSURE(!rSubtreeChange.isSetNodeChange(),"ERROR: Change type SET does not match group");
|
|
|
|
|
|
|
|
pNode->groupImpl().failedCommit(rSubtreeChange);
|
|
|
|
doFailedSubCommitted( rSubtreeChange, nNode);
|
|
|
|
}
|
2001-06-20 14:44:49 -05:00
|
|
|
else
|
|
|
|
OSL_ENSURE(nNode == root() && pNode->isValueElementNode(), "TreeImpl: Cannot finish commit: Unexpected node type");
|
2000-12-07 07:48:18 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
void TreeImpl::doAdjustToChanges(NodeChangesInformation& rLocalChanges, SubtreeChange const& rSubtreeChange, NodeOffset nNode, TreeDepth nDepth)
|
2000-11-19 18:38:19 -06:00
|
|
|
{
|
|
|
|
OSL_ASSERT(isValidNode(nNode));
|
|
|
|
Node* pNode = node(nNode);
|
|
|
|
|
2001-06-21 06:02:38 -05:00
|
|
|
OSL_ENSURE(rSubtreeChange.getNodeName() == getNodeName(nNode).toString(), "ERROR: Change name does not match node");
|
2000-11-19 18:38:19 -06:00
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
if (pNode->isSetNode())
|
2000-11-19 18:38:19 -06:00
|
|
|
{
|
|
|
|
OSL_ENSURE(rSubtreeChange.isSetNodeChange(),"ERROR: Change type GROUP does not match set");
|
|
|
|
|
2001-04-19 09:16:55 -05:00
|
|
|
pNode->setImpl().adjustToChanges(rLocalChanges, rSubtreeChange, nDepth);
|
2000-11-19 18:38:19 -06:00
|
|
|
}
|
2001-06-20 14:44:49 -05:00
|
|
|
else if (pNode->isGroupNode())
|
2000-11-19 18:38:19 -06:00
|
|
|
{
|
|
|
|
OSL_ENSURE(!rSubtreeChange.isSetNodeChange(),"ERROR: Change type SET does not match group");
|
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
pNode->groupImpl().adjustToChanges(rLocalChanges, rSubtreeChange, *this, nNode);
|
2001-04-19 09:16:55 -05:00
|
|
|
doAdjustToSubChanges( rLocalChanges, rSubtreeChange, nNode, nDepth);
|
2000-11-19 18:38:19 -06:00
|
|
|
}
|
2001-06-20 14:44:49 -05:00
|
|
|
else // might occur on external change (?)
|
|
|
|
{
|
|
|
|
OSL_ENSURE(pNode->isValueElementNode(), "TreeImpl: Unknown node type to adjust to changes");
|
|
|
|
|
|
|
|
OSL_ENSURE(nNode == root(), "TreeImpl: Unexpected node type - non-root value element");
|
|
|
|
|
|
|
|
OSL_ENSURE(false,"ERROR: Change type does not match node: Trying to apply subtree change to value element.");
|
|
|
|
}
|
2000-11-19 18:38:19 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2000-11-10 05:21:00 -06:00
|
|
|
void TreeImpl::doCommitSubChanges(SubtreeChange& aChangesParent, NodeOffset nParentNode)
|
|
|
|
{
|
|
|
|
for(NodeOffset nNode = firstChild(nParentNode); nNode != 0; nNode = findNextChild(nParentNode,nNode) )
|
|
|
|
{
|
|
|
|
if (node(nNode)->hasChanges())
|
2001-06-20 14:44:49 -05:00
|
|
|
{
|
|
|
|
std::auto_ptr<SubtreeChange> aSubChanges( doCommitChanges(nNode) );
|
|
|
|
std::auto_ptr<Change> aSubChangesBase( aSubChanges.release() );
|
|
|
|
aChangesParent.addChange( aSubChangesBase );
|
|
|
|
}
|
2000-11-10 05:21:00 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TreeImpl::doFinishSubCommitted(SubtreeChange& aChangesParent, NodeOffset nParentNode)
|
|
|
|
{
|
|
|
|
for(SubtreeChange::MutatingChildIterator
|
|
|
|
it = aChangesParent.begin_changes(),
|
|
|
|
stop = aChangesParent.end_changes();
|
|
|
|
it != stop;
|
|
|
|
++it)
|
|
|
|
{
|
2001-06-20 14:44:49 -05:00
|
|
|
if ( it->ISA(SubtreeChange) )
|
|
|
|
{
|
|
|
|
NodeOffset nNode = findChild(nParentNode, Name(it->getNodeName(), Name::NoValidate()) );
|
|
|
|
OSL_ENSURE( nNode != 0, "Changed sub-node not found in tree");
|
2000-11-10 05:21:00 -06:00
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
doFinishCommit(static_cast<SubtreeChange&>(*it),nNode);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OSL_ENSURE(it->ISA(ValueChange), "Unexpected change type for child of group node; change is ignored");
|
|
|
|
OSL_ENSURE(0 == findChild(nParentNode, Name(it->getNodeName(), Name::NoValidate())),
|
|
|
|
"Found sub(tree) node where a value was expected");
|
|
|
|
}
|
2000-11-10 05:21:00 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TreeImpl::doRevertSubCommitted(SubtreeChange& aChangesParent, NodeOffset nParentNode)
|
|
|
|
{
|
|
|
|
for(SubtreeChange::MutatingChildIterator
|
|
|
|
it = aChangesParent.begin_changes(),
|
|
|
|
stop = aChangesParent.end_changes();
|
|
|
|
it != stop;
|
|
|
|
++it)
|
|
|
|
{
|
2001-06-20 14:44:49 -05:00
|
|
|
if ( it->ISA(SubtreeChange) )
|
|
|
|
{
|
|
|
|
NodeOffset nNode = findChild(nParentNode, Name(it->getNodeName(), Name::NoValidate()) );
|
|
|
|
OSL_ENSURE( nNode != 0, "Changed sub-node not found in tree");
|
2000-11-10 05:21:00 -06:00
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
doRevertCommit(static_cast<SubtreeChange&>(*it),nNode);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OSL_ENSURE(it->ISA(ValueChange), "Unexpected change type for child of group node; change is ignored");
|
|
|
|
OSL_ENSURE(0 == findChild(nParentNode, Name(it->getNodeName(), Name::NoValidate())),
|
|
|
|
"Found sub(tree) node where a value was expected");
|
|
|
|
}
|
2000-11-10 05:21:00 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2000-12-07 07:48:18 -06:00
|
|
|
void TreeImpl::doFailedSubCommitted(SubtreeChange& aChangesParent, NodeOffset nParentNode)
|
|
|
|
{
|
|
|
|
for(SubtreeChange::MutatingChildIterator
|
|
|
|
it = aChangesParent.begin_changes(),
|
|
|
|
stop = aChangesParent.end_changes();
|
|
|
|
it != stop;
|
|
|
|
++it)
|
|
|
|
{
|
2001-06-20 14:44:49 -05:00
|
|
|
if ( it->ISA(SubtreeChange) )
|
|
|
|
{
|
|
|
|
NodeOffset nNode = findChild(nParentNode, Name(it->getNodeName(), Name::NoValidate()) );
|
|
|
|
OSL_ENSURE( nNode != 0, "Changed node not found in tree");
|
2000-12-07 07:48:18 -06:00
|
|
|
|
2001-06-20 14:44:49 -05:00
|
|
|
doFailedCommit(static_cast<SubtreeChange&>(*it),nNode);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OSL_ENSURE(it->ISA(ValueChange), "Unexpected change type for child of group node; change is ignored");
|
|
|
|
OSL_ENSURE(0 == findChild(nParentNode, Name(it->getNodeName(), Name::NoValidate())),
|
|
|
|
"Found sub(tree) node where a value was expected");
|
|
|
|
}
|
2000-12-07 07:48:18 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-02-13 10:16:59 -06:00
|
|
|
void TreeImpl::doAdjustToSubChanges(NodeChangesInformation& rLocalChanges, SubtreeChange const& aChangesParent, NodeOffset nParentNode,
|
2001-04-19 09:16:55 -05:00
|
|
|
TreeDepth nDepth)
|
2000-11-19 18:38:19 -06:00
|
|
|
{
|
|
|
|
for(SubtreeChange::ChildIterator
|
|
|
|
it = aChangesParent.begin(),
|
|
|
|
stop = aChangesParent.end();
|
|
|
|
it != stop;
|
|
|
|
++it)
|
|
|
|
{
|
2001-06-20 14:44:49 -05:00
|
|
|
if ( it->ISA(SubtreeChange) )
|
|
|
|
{
|
|
|
|
NodeOffset nNode = findChild(nParentNode, Name(it->getNodeName(), Name::NoValidate()) );
|
|
|
|
OSL_ENSURE( nNode != 0 || depthTo(nParentNode) >= getAvailableDepth(), "Changed node not found in tree");
|
|
|
|
|
|
|
|
if (nNode != 0)
|
|
|
|
{
|
|
|
|
OSL_ENSURE( nDepth > 0, "Depth is smaller than expected for tree");
|
|
|
|
doAdjustToChanges(rLocalChanges, static_cast<SubtreeChange const&>(*it),nNode,childDepth(nDepth));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2000-11-19 18:38:19 -06:00
|
|
|
{
|
2001-06-20 14:44:49 -05:00
|
|
|
OSL_ENSURE(it->ISA(ValueChange), "Unexpected change type for child of group node; change is ignored");
|
|
|
|
OSL_ENSURE(0 == findChild(nParentNode, Name(it->getNodeName(), Name::NoValidate())),
|
|
|
|
"Found sub(tree) node where a value was expected");
|
2000-11-19 18:38:19 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2000-11-07 07:35:59 -06:00
|
|
|
// Node Collection navigation
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
NodeOffset TreeImpl::parent(NodeOffset nNode) const
|
|
|
|
{
|
|
|
|
OSL_ASSERT(isValidNode(nNode));
|
|
|
|
return node(nNode)->parent();
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
2001-06-21 06:02:38 -05:00
|
|
|
inline // is private
|
|
|
|
Name TreeImpl::implGetOriginalName(NodeOffset nNode) const
|
|
|
|
{
|
|
|
|
OSL_ASSERT(isValidNode(nNode));
|
|
|
|
|
|
|
|
return node(nNode)->m_aName;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
Name TreeImpl::getNodeName(NodeOffset nNode) const
|
|
|
|
{
|
|
|
|
if (nNode == root()) return getRootName();
|
|
|
|
|
|
|
|
return implGetOriginalName(nNode);
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
2000-11-07 07:35:59 -06:00
|
|
|
|
2001-06-21 06:02:38 -05:00
|
|
|
Name TreeImpl::getRootName() const
|
2000-11-07 07:35:59 -06:00
|
|
|
{
|
2001-06-21 06:02:38 -05:00
|
|
|
return implGetOriginalName(root());
|
2000-11-07 07:35:59 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
TreeDepth TreeImpl::depthTo(NodeOffset nNode) const
|
|
|
|
{
|
|
|
|
OSL_ASSERT(isValidNode(nNode));
|
|
|
|
|
|
|
|
TreeDepth nDepth = 0;
|
|
|
|
while( 0 != (nNode=parent(nNode)) )
|
|
|
|
{
|
|
|
|
++nDepth;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nDepth;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TreeImpl::appendPathTo(NodeOffset nNode, Path::Components& rNames)
|
|
|
|
{
|
|
|
|
// nNode == 0 is handled correctly ...
|
|
|
|
OSL_ASSERT(nNode == 0 || isValidNode(nNode));
|
|
|
|
|
|
|
|
Path::Components::size_type nStart = rNames.size();
|
|
|
|
|
|
|
|
for (; nNode != 0; nNode = parent(nNode) )
|
|
|
|
{
|
|
|
|
OSL_ENSURE( isValidNode(nNode), "ERROR: Configuration: node has invalid parent");
|
2001-06-21 06:02:38 -05:00
|
|
|
rNames.push_back( getNodeName(nNode) );
|
2000-11-07 07:35:59 -06:00
|
|
|
}
|
|
|
|
std::reverse(rNames.begin() + nStart, rNames.end());
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Node iteration and access
|
|
|
|
NodeOffset TreeImpl::firstChild (NodeOffset nParent) const
|
|
|
|
{
|
|
|
|
return findNextChild(nParent,nParent);
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
NodeOffset TreeImpl::nextSibling(NodeOffset nNode) const
|
|
|
|
{
|
|
|
|
return findNextChild(parent(nNode),nNode);
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
NodeOffset TreeImpl::findNextChild(NodeOffset nParent, NodeOffset nStartAfter) const
|
|
|
|
{
|
|
|
|
OSL_ASSERT(isValidNode(nParent));
|
|
|
|
OSL_ASSERT(nStartAfter == 0 || isValidNode(nStartAfter));
|
|
|
|
|
|
|
|
NodeOffset nPos = nStartAfter ? nStartAfter : root()-1;
|
|
|
|
NodeOffset const nAfterLast = nodeCount() + root();
|
|
|
|
while (++nPos < nAfterLast)
|
|
|
|
{
|
|
|
|
if(parent(nPos) == nParent) return nPos;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
NodeOffset TreeImpl::findChild(NodeOffset nParent, Name const& aName) const
|
|
|
|
{
|
|
|
|
OSL_ASSERT(isValidNode(nParent));
|
|
|
|
|
|
|
|
NodeOffset nPos = nParent;
|
|
|
|
NodeOffset const nAfterLast = nodeCount() + root();
|
|
|
|
while (++nPos < nAfterLast)
|
|
|
|
{
|
2001-06-21 06:02:38 -05:00
|
|
|
if(parent(nPos) == nParent && getNodeName(nPos) == aName)
|
2000-11-07 07:35:59 -06:00
|
|
|
return nPos;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2000-11-09 08:11:17 -06:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// locking
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
ISynchronizedData* TreeImpl::getRootLock()
|
|
|
|
{
|
|
|
|
if ( m_pParentTree )
|
|
|
|
return m_pParentTree->getRootLock();
|
|
|
|
else
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
ISynchronizedData const* TreeImpl::getRootLock() const
|
|
|
|
{
|
|
|
|
if ( m_pParentTree )
|
|
|
|
return m_pParentTree->getRootLock();
|
|
|
|
else
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2000-11-07 07:35:59 -06:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2000-11-09 08:11:17 -06:00
|
|
|
void TreeImpl::acquireReadAccess() const
|
|
|
|
{
|
|
|
|
m_aOwnLock.acquireReadAccess();
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void TreeImpl::releaseReadAccess() const
|
|
|
|
{
|
|
|
|
m_aOwnLock.releaseReadAccess();
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void TreeImpl::acquireWriteAccess()
|
|
|
|
{
|
|
|
|
m_aOwnLock.acquireWriteAccess();
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void TreeImpl::releaseWriteAccess()
|
|
|
|
{
|
|
|
|
m_aOwnLock.releaseWriteAccess();
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2000-11-07 07:35:59 -06:00
|
|
|
// dynamic-casting
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
ElementTreeImpl * TreeImpl::asElementTree()
|
|
|
|
{
|
|
|
|
ElementTreeImpl const* const pResult = doCastToElementTree();
|
|
|
|
TreeImpl const* const pTest = pResult;
|
|
|
|
if (pTest== this)
|
|
|
|
return const_cast<ElementTreeImpl *>(pResult);
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
RootTreeImpl * TreeImpl::asRootTree()
|
|
|
|
{
|
|
|
|
RootTreeImpl const* const pResult = doCastToRootTree();
|
|
|
|
TreeImpl const* const pTest = pResult;
|
|
|
|
if (pTest== this)
|
|
|
|
return const_cast<RootTreeImpl *>(pResult);
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
ElementTreeImpl const* TreeImpl::asElementTree() const
|
|
|
|
{
|
|
|
|
return doCastToElementTree();
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
RootTreeImpl const* TreeImpl::asRootTree() const
|
|
|
|
{
|
|
|
|
return doCastToRootTree();
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
RootTreeImpl const* ElementTreeImpl::doCastToRootTree() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
ElementTreeImpl const* ElementTreeImpl::doCastToElementTree() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
RootTreeImpl const* RootTreeImpl::doCastToRootTree() const
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
ElementTreeImpl const* RootTreeImpl::doCastToElementTree() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// class RootTreeImpl
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
RootTreeImpl::RootTreeImpl( NodeFactory& rNodeFactory,
|
2000-11-19 18:38:19 -06:00
|
|
|
AbsolutePath const& aContextPath,
|
|
|
|
ISubtree& rCacheNode, TreeDepth nDepth,
|
|
|
|
TemplateProvider const& aTemplateProvider)
|
|
|
|
: TreeImpl()
|
2000-11-13 11:00:16 -06:00
|
|
|
, m_aContextPath(aContextPath)
|
2000-11-07 07:35:59 -06:00
|
|
|
{
|
2001-04-19 09:16:55 -05:00
|
|
|
TreeImpl::build(rNodeFactory,rCacheNode,nDepth,aTemplateProvider);
|
2000-11-07 07:35:59 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// class ElementTreeImpl
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
ElementTreeImpl::ElementTreeImpl( NodeFactory& rFactory,
|
|
|
|
INode& rCacheNode, TreeDepth nDepth,
|
2000-11-19 18:38:19 -06:00
|
|
|
TemplateHolder aTemplateInfo,
|
|
|
|
TemplateProvider const& aTemplateProvider )
|
2000-11-07 07:35:59 -06:00
|
|
|
: TreeImpl()
|
|
|
|
, m_aInstanceInfo(aTemplateInfo)
|
|
|
|
, m_pOwnedNode(0)
|
|
|
|
{
|
2000-11-19 18:38:19 -06:00
|
|
|
TreeImpl::build( rFactory, rCacheNode, nDepth, aTemplateProvider );
|
2000-11-07 07:35:59 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
ElementTreeImpl::ElementTreeImpl( NodeFactory& rFactory,
|
|
|
|
TreeImpl& rParentTree, NodeOffset nParentNode,
|
|
|
|
INode& rCacheNode, TreeDepth nDepth,
|
2000-11-19 18:38:19 -06:00
|
|
|
TemplateHolder aTemplateInfo,
|
|
|
|
TemplateProvider const& aTemplateProvider )
|
2001-04-19 09:16:55 -05:00
|
|
|
: TreeImpl( rParentTree, nParentNode )
|
2000-11-07 07:35:59 -06:00
|
|
|
, m_aInstanceInfo(aTemplateInfo)
|
|
|
|
, m_pOwnedNode(0)
|
|
|
|
{
|
2000-11-19 18:38:19 -06:00
|
|
|
TreeImpl::build( rFactory, rCacheNode, nDepth, aTemplateProvider );
|
2000-11-07 07:35:59 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2000-11-19 18:38:19 -06:00
|
|
|
ElementTreeImpl::ElementTreeImpl( std::auto_ptr<INode>& pNewNode,
|
|
|
|
TemplateHolder aTemplate,
|
|
|
|
TemplateProvider const& aTemplateProvider )
|
2000-11-07 07:35:59 -06:00
|
|
|
: TreeImpl()
|
|
|
|
, m_aInstanceInfo(aTemplate)
|
|
|
|
, m_pOwnedNode(0)
|
|
|
|
{
|
|
|
|
if (!pNewNode.get())
|
|
|
|
{
|
|
|
|
throw Exception("ERROR: Provider can't create Element Instance From Template");
|
|
|
|
}
|
|
|
|
|
2000-11-19 18:38:19 -06:00
|
|
|
TreeImpl::build( NodeType::getDirectAccessFactory(), *pNewNode, c_TreeDepthAll, aTemplateProvider );
|
2000-11-07 07:35:59 -06:00
|
|
|
m_pOwnedNode = pNewNode.release();
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
ElementTreeImpl::~ElementTreeImpl()
|
|
|
|
{
|
|
|
|
delete m_pOwnedNode;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2000-12-04 02:10:21 -06:00
|
|
|
void ElementTreeImpl::disposeData()
|
|
|
|
{
|
|
|
|
TreeImpl::disposeData();
|
|
|
|
delete m_pOwnedNode;
|
|
|
|
m_pOwnedNode = 0;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2000-11-07 07:35:59 -06:00
|
|
|
// ownership handling
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/// transfer ownership to the given set
|
|
|
|
void ElementTreeImpl::attachTo(ISubtree& rOwningSet, Name const& aElementName)
|
|
|
|
{
|
|
|
|
OSL_ENSURE(m_pOwnedNode,"ERROR: Cannot add a non-owned node to a subtree");
|
|
|
|
|
|
|
|
if (m_pOwnedNode)
|
|
|
|
{
|
2001-06-21 06:02:38 -05:00
|
|
|
OSL_ENSURE(this->getRootName() == aElementName,"ElementTree: Attaching with unexpected element name");
|
2000-11-07 07:35:59 -06:00
|
|
|
m_pOwnedNode->setName(aElementName.toString());
|
|
|
|
|
|
|
|
std::auto_ptr<INode> aNode(m_pOwnedNode);
|
|
|
|
m_pOwnedNode = 0;
|
|
|
|
|
|
|
|
rOwningSet.addChild(aNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/// tranfer ownership from the given set
|
|
|
|
void ElementTreeImpl::detachFrom(ISubtree& rOwningSet, Name const& aElementName)
|
|
|
|
{
|
|
|
|
OSL_ENSURE(!m_pOwnedNode,"ERROR: Cannot detach a already owned node from a subtree");
|
|
|
|
if (!m_pOwnedNode)
|
|
|
|
{
|
2001-06-21 06:02:38 -05:00
|
|
|
OSL_ENSURE(this->getRootName() == aElementName,"ElementTree: Detaching with unexpected element name");
|
2000-11-07 07:35:59 -06:00
|
|
|
std::auto_ptr<INode> aNode( rOwningSet.removeChild(aElementName.toString()) );
|
|
|
|
OSL_ENSURE(aNode.get(),"ERROR: Detached node not found in the given subtree");
|
|
|
|
|
|
|
|
m_pOwnedNode = aNode.release();
|
|
|
|
}
|
|
|
|
}
|
2000-11-10 05:21:00 -06:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/// transfer ownership from the given owner
|
|
|
|
void ElementTreeImpl::takeNodeFrom(std::auto_ptr<INode>& rOldOwner)
|
|
|
|
{
|
|
|
|
OSL_ENSURE(!m_pOwnedNode,"ERROR: Cannot take over a node - already owning");
|
|
|
|
OSL_ENSURE(rOldOwner.get(),"ERROR: Cannot take over NULL node");
|
|
|
|
if (!m_pOwnedNode)
|
|
|
|
{
|
|
|
|
m_pOwnedNode = rOldOwner.release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/// transfer ownership to the given owner
|
|
|
|
void ElementTreeImpl::releaseTo(std::auto_ptr<INode>& rNewOwner)
|
|
|
|
{
|
|
|
|
OSL_ENSURE(m_pOwnedNode,"ERROR: Cannot release a non-owned node");
|
2001-02-23 03:50:59 -06:00
|
|
|
if (m_pOwnedNode)
|
|
|
|
{
|
2001-06-21 06:02:38 -05:00
|
|
|
Name aNodeName = getRootName();
|
2001-02-23 03:50:59 -06:00
|
|
|
m_pOwnedNode->setName( aNodeName.toString() );
|
|
|
|
}
|
2000-11-10 05:21:00 -06:00
|
|
|
|
|
|
|
rNewOwner.reset(m_pOwnedNode);
|
|
|
|
m_pOwnedNode = 0;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/// transfer ownership to the given owner, also providing a new name
|
|
|
|
void ElementTreeImpl::releaseAs(std::auto_ptr<INode>& rNewOwner, Name const& aElementName)
|
|
|
|
{
|
|
|
|
OSL_ENSURE(m_pOwnedNode,"ERROR: Cannot release and rename a non-owned node");
|
|
|
|
|
|
|
|
if (m_pOwnedNode)
|
|
|
|
renameTree(aElementName);
|
|
|
|
|
2001-02-23 03:50:59 -06:00
|
|
|
this->releaseTo(rNewOwner);
|
2000-11-10 05:21:00 -06:00
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
2000-11-07 07:35:59 -06:00
|
|
|
|
|
|
|
// context handling
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/// renames the tree's root without concern for context consistency !
|
|
|
|
void ElementTreeImpl::renameTree(Name const& aNewName)
|
|
|
|
{
|
|
|
|
node(root())->renameNode(aNewName);
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void ElementTreeImpl::moveTree(TreeImpl* pParentTree, NodeOffset nParentNode)
|
|
|
|
{
|
|
|
|
TreeImpl::setContext(pParentTree,nParentNode);
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void ElementTreeImpl::detachTree()
|
|
|
|
{
|
|
|
|
TreeImpl::clearContext();
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
} // namespace configuration
|
|
|
|
} // namespace configmgr
|
|
|
|
|