Files
libreoffice/configmgr/source/tree/builddata.cxx
Jens-Heiner Rechtien 5c27051c87 #65293#: syntax
2002-02-18 17:25:24 +00:00

1301 lines
44 KiB
C++
Raw Blame History

/*************************************************************************
*
* $RCSfile: builddata.cxx,v $
*
* $Revision: 1.3 $
*
* last change: $Author: hr $ $Date: 2002-02-18 18:25:24 $
*
* 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): _______________________________________
*
*
************************************************************************/
#include "builddata.hxx"
#ifndef CONFIGMGR_TREEADDRESS_HXX
#include "treeaddress.hxx"
#endif
#ifndef CONFIGMGR_TREEACCESSOR_HXX
#include "treeaccessor.hxx"
#endif
#ifndef CONFIGMGR_ACCESSOR_HXX
#include "accessor.hxx"
#endif
#ifndef CONFIGMGR_UPDATEACCESSOR_HXX
#include "updateaccessor.hxx"
#endif
#ifndef CONFIGMGR_NODEACCESS_HXX
#include "nodeaccess.hxx"
#endif
#ifndef CONFIGMGR_SETNODEACCESS_HXX
#include "setnodeaccess.hxx"
#endif
#ifndef CONFIGMGR_VALUENODEACCESS_HXX
#include "valuenodeaccess.hxx"
#endif
#ifndef CONFIGMGR_GROUPNODEACCESS_HXX
#include "groupnodeaccess.hxx"
#endif
#ifndef CONFIGMGR_NODEVISITOR_HXX
#include "nodevisitor.hxx"
#endif
#ifndef INCLUDED_SHARABLE_NODE_HXX
#include "node.hxx"
#endif
#ifndef INCLUDED_SHARABLE_TREEFRAGMENT_HXX
#include "treefragment.hxx"
#endif
#ifndef _CONFIGMGR_TREE_VALUENODE_HXX
#include "valuenode.hxx"
#endif
#ifndef CONFIGMGR_TREE_NODEFACTORY_HXX
#include "treenodefactory.hxx"
#endif
#ifndef INCLUDED_CSTDDEF
#include <cstddef>
#define INCLUDED_CSTDDEF
#endif
#ifndef INCLUDED_ALGORITHM
#include <algorithm>
#define INCLUDED_ALGORITHM
#endif
namespace configmgr
{
//-----------------------------------------------------------------------------
typedef ValueNode OValueNode; // to avoid ambiguity with sharable::ValueNode
//-----------------------------------------------------------------------------
namespace data
{
//-------------------------------------------------------------------------
using namespace sharable;
using memory::Pointer;
using memory::Accessor;
using memory::Allocator;
using memory::UpdateAccessor;
//-----------------------------------------------------------------------------
static
inline
NodeAddress offsetNodeBy(NodeAddress _aNode, Offset _nOffset)
{
Address aRawAddr = _aNode.addressValue() + _nOffset * sizeof(Node);
return NodeAddress(Pointer(aRawAddr));
}
static
inline
NodeAddress addressOfNodeAt(TreeAddress _aTree, Offset _nOffset)
{
Address aRawAddr = _aTree.addressValue() +
offsetof(TreeFragment,nodes) +
_nOffset * sizeof(Node);
return NodeAddress(Pointer(aRawAddr));
}
//-----------------------------------------------------------------------------
class TreeNodeBuilder
{
TreeFragmentHeader m_header;
std::vector< Node > m_nodes;
Offset m_parent;
public:
TreeNodeBuilder() : m_header(), m_nodes(), m_parent() {}
TreeFragmentHeader & header() { return m_header; }
Node & nodeAt(Offset _pos) { checkOffset(_pos); return m_nodes[_pos]; }
NodeInfo & nodeInfoAt(Offset _pos) { checkOffset(_pos); return m_nodes[_pos].node.info; }
Node & lastNode() { checkOffset(0); return m_nodes.back(); }
NodeInfo & lastNodeInfo() { checkOffset(0); return m_nodes.back().node.info; }
void resetTreeFragment();
void resetTreeFragment(sharable::String _treeName, State::Field _state);
TreeAddress createTreeFragment(UpdateAccessor & _anUpdater);
Offset startGroup( Name _aName, Flags::Field _aFlags );
void endGroup( Offset _nPos );
void addSet( Name _aName, Flags::Field _aFlags, Address _aElementType );
void addValue( Name _aName, Flags::Field _aFlags,
AnyData::TypeCode _aValueType,
AnyData _aUserValue,
AnyData _aDefaultName );
public:
class CollectSetElements;
class LinkSetNodes;
private:
TreeAddress allocTreeFragment(UpdateAccessor & _anUpdater);
void linkTreeFragment(UpdateAccessor & _anUpdater, TreeAddress _aTreeAddr);
Offset addNode(Name _aName, Flags::Field _aFlags, Type::Field _aType);
void checkOffset(Offset _pos);
};
//-----------------------------------------------------------------------------
class TreeNodeBuilder::CollectSetElements
{
UpdateAccessor & m_updater;
TreeAddress m_head;
public:
explicit
CollectSetElements(UpdateAccessor & _anUpdater)
: m_updater(_anUpdater)
{
}
void resetElementList();
void addElement(TreeAddress _aNewElement);
List getElementListAndClear();
UpdateAccessor & updater() const { return m_updater; }
};
//-----------------------------------------------------------------------------
class TreeNodeBuilder::LinkSetNodes : private SetVisitor
{
UpdateAccessor & m_updater;
NodeAddress m_aParentAddr;
public:
explicit
LinkSetNodes(UpdateAccessor & _anUpdater)
: m_updater(_anUpdater)
, m_aParentAddr()
{
}
Result linkTree(TreeAddress const & _aFragment);
Result linkSet(SetNodeAccess const & _aSet);
private:
Result handle(TreeAccessor const & _aElement);
Result handle(SetNodeAccess const & _aSet);
};
//-----------------------------------------------------------------------------
class BasicDataTreeBuilder
{
public:
explicit
BasicDataTreeBuilder(UpdateAccessor & _anUpdater)
: m_updater(_anUpdater)
{}
TreeAddress createTree() { return m_builder.createTreeFragment(m_updater); }
protected:
TreeNodeBuilder& builder() { return m_builder; }
UpdateAccessor & updater() const { return m_updater; }
Accessor accessor() const { return m_updater.accessor(); }
Allocator allocator() const { return m_updater.allocator(); }
private:
UpdateAccessor & m_updater;
TreeNodeBuilder m_builder;
};
//-----------------------------------------------------------------------------
class ConvertingDataTreeBuilder : private NodeAction, public BasicDataTreeBuilder
{
rtl::OUString m_sRootName;
bool m_bWithDefaults;
public:
explicit
ConvertingDataTreeBuilder(UpdateAccessor & _anUpdater)
: BasicDataTreeBuilder(_anUpdater)
{}
TreeAddress buildTree(OUString const & _aTreeName, INode const& _aNode, bool _bWithDefault);
TreeAddress buildElement(INode const& _aNode, OUString const & _aTypeName, bool _bWithDefault);
private:
class ElementListBuilder;
virtual void handle(ISubtree const & _aNode);
virtual void handle(OValueNode const & _aNode);
Address makeTemplateData(rtl::OUString const & _aTemplateName, rtl::OUString const & _aTemplateModule);
Name allocName(INode const & _aNode);
State::Field makeState(node::Attributes const & _aAttributes);
Flags::Field makeFlags(node::Attributes const & _aAttributes);
};
//-----------------------------------------------------------------------------
class ConvertingDataTreeBuilder::ElementListBuilder : private NodeAction
{
TreeNodeBuilder::CollectSetElements m_aCollector;
rtl::OUString m_sTypeName;
bool m_bWithDefaults;
public:
explicit
ElementListBuilder(UpdateAccessor & _anUpdater)
: m_aCollector(_anUpdater)
, m_sTypeName()
, m_bWithDefaults()
{}
List buildElementList(ISubtree const & _aSet, bool _bWithDefaults);
private:
void handleNode(INode const & _aSourceNode);
void handle(OValueNode const & _aSourceNode);
void handle(ISubtree const & _aSourceNode);
};
//-----------------------------------------------------------------------------
class CopyingDataTreeBuilder : private NodeVisitor, public BasicDataTreeBuilder
{
public:
explicit
CopyingDataTreeBuilder(UpdateAccessor & _anUpdater)
: BasicDataTreeBuilder(_anUpdater)
{}
TreeAddress buildTree(TreeAccessor const & _aSourceTree);
private:
class ElementListBuilder;
Result handle(ValueNodeAccess const & _aNode);
Result handle(GroupNodeAccess const & _aNode);
Result handle(SetNodeAccess const & _aNode);
Address makeTemplateData(Accessor const & _aSourceAccessor, Address _aSourceTemplate);
};
//-----------------------------------------------------------------------------
class CopyingDataTreeBuilder::ElementListBuilder : private SetVisitor
{
TreeNodeBuilder::CollectSetElements m_aCollector;
public:
explicit
ElementListBuilder(UpdateAccessor & _anUpdater)
: m_aCollector(_anUpdater)
{}
List buildElementList(SetNodeAccess const & _aSet);
private:
Result handle(TreeAccessor const & _aSourceTree);
};
//-----------------------------------------------------------------------------
class ConvertingNodeBuilder : private NodeVisitor
{
OTreeNodeFactory & m_rNodeFactory;
std::auto_ptr<INode> m_pNode;
public:
ConvertingNodeBuilder(OTreeNodeFactory & _rNodeFactory)
: m_rNodeFactory(_rNodeFactory)
, m_pNode()
{
}
std::auto_ptr<INode> buildNode(TreeAccessor const& _aTree, bool _bUseTreeName);
std::auto_ptr<INode> buildNode(NodeAccess const& _aTree);
std::auto_ptr<ISubtree> buildNodeTree(GroupNodeAccess const& _aGroupNode) const;
std::auto_ptr<ISubtree> buildNodeTree(SetNodeAccess const& _aSetNode) const;
std::auto_ptr<OValueNode> buildNodeTree(ValueNodeAccess const& _aValueNode) const
{ return this->convertNode(_aValueNode); }
static node::Attributes convertAttributes(NodeAccess const& _aNode)
{ return _aNode.getAttributes(); }
private:
std::auto_ptr<ISubtree> convertNode(GroupNodeAccess const& _aGroupNode) const;
std::auto_ptr<ISubtree> convertNode(SetNodeAccess const& _aSetNode) const;
std::auto_ptr<OValueNode> convertNode(ValueNodeAccess const& _aValueNode) const;
Result handle(ValueNodeAccess const & _aNode);
Result handle(GroupNodeAccess const & _aNode);
Result handle(SetNodeAccess const & _aNode);
};
//-----------------------------------------------------------------------------
class ConvertingSubnodeBuilder : private SetVisitor
{
ConvertingNodeBuilder m_aSubnodeBuilder;
ISubtree & m_rParentNode;
public:
ConvertingSubnodeBuilder(OTreeNodeFactory & _rNodeFactory, ISubtree & _rParentNode)
: m_aSubnodeBuilder(_rNodeFactory)
, m_rParentNode(_rParentNode)
{
}
void addElements(SetNodeAccess const & _aSet) { this->visitElements(_aSet); }
void addChildren(GroupNodeAccess const & _aGroup) { this->visitChildren(_aGroup); }
private:
Result handle(TreeAccessor const & _aElement);
Result handle(NodeAccess const & _aMember);
};
//-----------------------------------------------------------------------------
class DataTreeDefaultMerger : private NodeAction
{
public:
explicit
DataTreeDefaultMerger(UpdateAccessor & _anUpdater)
: m_updater(_anUpdater)
{}
void mergeDefaults(TreeAddress _aBaseAddress, INode const& _aDefaultNode);
private:
void handle(OValueNode const & _aNode);
void handle(ISubtree const & _aNode);
protected:
UpdateAccessor & updater() const { return m_updater; }
Accessor accessor() const { return m_updater.accessor(); }
Allocator allocator() const { return m_updater.allocator(); }
private:
UpdateAccessor & m_updater;
};
//-----------------------------------------------------------------------------
class DataTreeCleanup
{
public:
explicit
DataTreeCleanup(UpdateAccessor & _anUpdater)
: m_updater(_anUpdater)
{}
TreeAddress destroyTree(TreeAddress _aBaseAddress);
private:
void destroyNode(NodeAddress _aNodeAddress);
void destroyData(TreeFragmentHeader * _pHeader);
void destroyData(NodeInfo * _pNodeInfo);
void destroyData(sharable::GroupNode * _pNode);
void destroyData(sharable::ValueNode * _pNode);
void destroyData(sharable::SetNode * _pNode);
private:
UpdateAccessor & updater() const { return m_updater; }
Accessor accessor() const { return m_updater.accessor(); }
Allocator allocator() const { return m_updater.allocator(); }
private:
UpdateAccessor & m_updater;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
TreeAddress buildTree(memory::UpdateAccessor& _aTargetMemory, TreeAccessor const& _aTree)
{
CopyingDataTreeBuilder aBuilder(_aTargetMemory);
TreeAddress aResult = aBuilder.buildTree(_aTree);
return aResult;
}
//-----------------------------------------------------------------------------
TreeAddress buildTree(memory::UpdateAccessor& _aTargetMemory, rtl::OUString const & _aTreeName, INode const& _aNode, bool _bWithDefaults)
{
ConvertingDataTreeBuilder aBuilder(_aTargetMemory);
TreeAddress aResult = aBuilder.buildTree(_aTreeName, _aNode,_bWithDefaults);
return aResult;
}
//-----------------------------------------------------------------------------
TreeAddress buildElementTree(memory::UpdateAccessor& _aTargetMemory, INode const& _aNode, rtl::OUString const & _aTypeName, bool _bWithDefaults)
{
ConvertingDataTreeBuilder aBuilder(_aTargetMemory);
TreeAddress aResult = aBuilder.buildElement(_aNode, _aTypeName, _bWithDefaults);
return aResult;
}
//-----------------------------------------------------------------------------
void mergeDefaults(memory::UpdateAccessor& _aTargetMemory, TreeAddress _aBaseAddress, INode const& _aDefaultNode)
{
DataTreeDefaultMerger aMergeHelper(_aTargetMemory);
aMergeHelper.mergeDefaults(_aBaseAddress, _aDefaultNode);
}
//-----------------------------------------------------------------------------
void destroyTree(memory::UpdateAccessor& _aTreeMemory, TreeAddress _aBaseAddress)
{
DataTreeCleanup aCleaner(_aTreeMemory);
aCleaner.destroyTree(_aBaseAddress);
}
//-----------------------------------------------------------------------------
std::auto_ptr<INode> convertTree(TreeAccessor const & _aTree, bool _bUseTreeName)
{
ConvertingNodeBuilder aBuilder( configmgr::getDefaultTreeNodeFactory() );
return aBuilder.buildNode(_aTree,_bUseTreeName);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
inline
void TreeNodeBuilder::CollectSetElements::resetElementList()
{
OSL_ENSURE(m_head.isNull(), "Joining to a element list that was forgotten");
}
//-----------------------------------------------------------------------------
inline
List TreeNodeBuilder::CollectSetElements::getElementListAndClear()
{
List aResult = m_head.addressValue();
m_head = TreeAddress();
return aResult;
}
//-----------------------------------------------------------------------------
void TreeNodeBuilder::CollectSetElements::addElement(TreeAddress _aNewElement)
{
if (TreeFragment * pNewFragment = TreeAccessor::access(_aNewElement,m_updater))
{
pNewFragment->header.parent = 0; // data not available here
pNewFragment->header.next = m_head.addressValue();
m_head = _aNewElement;
}
else
OSL_ENSURE(false, "Cannot add NULL element");
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
NodeVisitor::Result TreeNodeBuilder::LinkSetNodes::linkTree(TreeAddress const & _aTree)
{
TreeAccessor aTreeAccess(m_updater.accessor(), _aTree);
TreeFragment const & rTreeData = aTreeAccess.data();
NodeAddress aOldParent = m_aParentAddr;
m_aParentAddr = NodeAddress();
Result eResult = CONTINUE;
Offset nCount = rTreeData.header.count;
for(Offset i=0; i < nCount; ++i)
{
NodeAccess aNode(aTreeAccess.accessor(),&rTreeData.nodes[i]);
eResult =this->visitNode( aNode );
if (eResult == DONE) break;
}
m_aParentAddr = aOldParent;
return eResult;
}
//-----------------------------------------------------------------------------
NodeVisitor::Result TreeNodeBuilder::LinkSetNodes::linkSet(SetNodeAccess const & _aSet)
{
OSL_ENSURE(m_aParentAddr.isNull(),"Linking set data already in progress");
m_aParentAddr = _aSet.address();
Result aResult = this->visitElements(_aSet);
m_aParentAddr = NodeAddress();
return aResult;
}
//-----------------------------------------------------------------------------
NodeVisitor::Result TreeNodeBuilder::LinkSetNodes::handle(TreeAccessor const & _aSourceTree)
{
OSL_ENSURE(m_aParentAddr.is(),"Cannot link set element without parent address");
TreeFragment * pFragment = _aSourceTree.access(_aSourceTree.address(), m_updater);
pFragment->header.parent = m_aParentAddr.addressValue();
return CONTINUE;
}
//-----------------------------------------------------------------------------
NodeVisitor::Result TreeNodeBuilder::LinkSetNodes::handle(SetNodeAccess const & _aNode)
{
return this->linkSet(_aNode);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
inline void TreeNodeBuilder::checkOffset(Offset _pos)
{
OSL_ENSURE(_pos < m_nodes.size(), "TreeNodeBuilder: Node access past end.");
}
//-----------------------------------------------------------------------------
Offset TreeNodeBuilder::addNode(Name _aName, Flags::Field _aFlags, Type::Field _aType)
{
OSL_PRECOND(_aName, "TreeNodeBuilder: Unexpected NULL name");
// TODO: consistenc<6E> checks for flags
OSL_ENSURE(m_nodes.size() == m_header.count, "TreeNodeBuilder: node count mismatch");
Offset nNewOffset = m_header.count++;
m_nodes.push_back( Node() );
OSL_ASSERT( &lastNode() == &nodeAt(nNewOffset) );
NodeInfo & rInfo = lastNode().node.info;
rInfo.name = _aName;
rInfo.flags = _aFlags;
rInfo.type = _aType;
OSL_ENSURE(0 <= m_parent && m_parent <= nNewOffset, "ERROR - TreeNodeBuilder: invalid parent");
OSL_ENSURE( (nNewOffset == 0) == (nNewOffset == m_parent), "ERROR - TreeNodeBuilder: node is own parent");
rInfo.parent = nNewOffset - m_parent;
return nNewOffset;
}
//-----------------------------------------------------------------------------
void TreeNodeBuilder::resetTreeFragment()
{
State::Field nNullState = State::merged | State::flag_mandatory | State::flag_readonly;
this->resetTreeFragment(0,nNullState);
}
//-----------------------------------------------------------------------------
void TreeNodeBuilder::resetTreeFragment(sharable::String _name, State::Field _state)
{
m_header.next = 0;
m_header.name = _name;
m_header.parent = 0;
m_header.count = 0;
m_header.state = _state;
m_nodes.clear();
m_parent = 0;
}
//-----------------------------------------------------------------------------
TreeAddress TreeNodeBuilder::allocTreeFragment(UpdateAccessor & _anUpdater)
{
OSL_ENSURE(m_nodes.size() == m_header.count, "TreeNodeBuilder: node count mismatch");
sal_uInt32 const nFragmentSize = sizeof(TreeFragment) + (m_header.count-1)*sizeof(Node);
OSL_ASSERT(nFragmentSize >= sizeof m_header + m_header.count*sizeof(Node));
Address aBaseAddress = _anUpdater.allocator().allocate(nFragmentSize);
TreeAddress aResult( static_cast<memory::Pointer>(aBaseAddress) );
if (TreeFragment * pFragment = TreeAccessor::access(aResult,_anUpdater))
{
pFragment->header = m_header;
std::copy(m_nodes.begin(),m_nodes.end(),pFragment->nodes);
}
return aResult;
}
//-----------------------------------------------------------------------------
void TreeNodeBuilder::linkTreeFragment(UpdateAccessor & _anUpdater, TreeAddress _aTreeFragment)
{
LinkSetNodes(_anUpdater).linkTree(_aTreeFragment);
}
//-----------------------------------------------------------------------------
TreeAddress TreeNodeBuilder::createTreeFragment(UpdateAccessor & _anUpdater)
{
TreeAddress aResult = allocTreeFragment(_anUpdater);
if (aResult.is())
{
linkTreeFragment(_anUpdater,aResult);
m_nodes.clear(); // ownership of indirect data has gone ...
}
return aResult;
}
//-----------------------------------------------------------------------------
Offset TreeNodeBuilder::startGroup( Name _aName, Flags::Field _aFlags )
{
Offset nNewIndex = addNode(_aName,_aFlags,Type::nodetype_group);
lastNode().group.numDescendants = 0;
m_parent = nNewIndex;
return nNewIndex;
}
//-----------------------------------------------------------------------------
void TreeNodeBuilder::endGroup( Offset _nPos )
{
// while (_nPos < m_parent) endGroup(m_parent);
OSL_PRECOND(_nPos == m_parent, "TreeNodeBuilder: Group being closed is not the current parent");
OSL_ENSURE(nodeAt(_nPos).isGroup(), "TreeNodeBuilder: Group being closed is not a group");
OSL_ENSURE(m_nodes.size() == m_header.count, "TreeNodeBuilder: node count mismatch");
GroupNode & rGroup = nodeAt(_nPos).group;
rGroup.numDescendants = m_nodes.size() - _nPos - 1;
m_parent -= rGroup.info.parent;
}
//-----------------------------------------------------------------------------
void TreeNodeBuilder::addSet( Name _aName, Flags::Field _aFlags, Address _aElementType )
{
Offset nNewIndex = addNode(_aName,_aFlags,Type::nodetype_set);
lastNode().set.elementType = _aElementType;
lastNode().set.elements = 0;
}
//-----------------------------------------------------------------------------
void TreeNodeBuilder::addValue( Name _aName, Flags::Field _aFlags,
AnyData::TypeCode _aValueType,
AnyData _aUserValue,
AnyData _aDefaultValue )
{
OSL_PRECOND(_aValueType == (_aValueType & Type::mask_valuetype), "TreeNodeBuilder: invalid value type");
Offset nNewIndex = addNode(_aName,_aFlags,Type::nodetype_value | _aValueType);
lastNode().value.value = _aUserValue;
lastNode().value.defaultValue = _aDefaultValue;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
TreeAddress CopyingDataTreeBuilder::buildTree(TreeAccessor const & _aSourceTree)
{
OSL_ENSURE(_aSourceTree.isValid(), "Trying to build a tree from NULL data");
if (!_aSourceTree.isValid()) return TreeAddress();
TreeFragment const & aSrc = _aSourceTree.data();
sharable::String aTreeName = allocString( allocator(), aSrc.getName(_aSourceTree.accessor()));
this->builder().resetTreeFragment(aTreeName, aSrc.header.state);
this->visitNode(_aSourceTree.getRootNode());
return this->createTree();
}
//-----------------------------------------------------------------------------
NodeVisitor::Result CopyingDataTreeBuilder::handle(ValueNodeAccess const & _aNode)
{
sharable::ValueNode const & aSrc = _aNode.data();
sharable::Name aNodeName = allocName( allocator(), aSrc.info.getName(_aNode.accessor()));
Flags::Field aFlags = aSrc.info.flags;
AnyData::TypeCode aType = aSrc.info.type & Type::mask_valuetype;
AnyData aNewValue, aNewDefault;
if (aFlags & Flags::valueAvailable)
aNewValue = allocData(allocator(), aType, aSrc.getUserValue(_aNode.accessor()));
else
aNewValue.data = 0;
if (aFlags & Flags::defaultAvailable)
aNewDefault = allocData(allocator(), aType, aSrc.getDefaultValue(_aNode.accessor()));
else
aNewDefault.data = 0;
this->builder().addValue(aNodeName,aFlags,aType,aNewValue,aNewDefault);
return CONTINUE;
}
//-----------------------------------------------------------------------------
NodeVisitor::Result CopyingDataTreeBuilder::handle(GroupNodeAccess const & _aNode)
{
sharable::GroupNode const & aSrc = _aNode.data();
sharable::Name aNodeName = allocName( allocator(), aSrc.info.getName(_aNode.accessor()));
Flags::Field aFlags = aSrc.info.flags;
Offset nGroupOffset = this->builder().startGroup(aNodeName,aFlags);
this->visitChildren(_aNode);
this->builder().endGroup(nGroupOffset);
return CONTINUE;
}
//-----------------------------------------------------------------------------
NodeVisitor::Result CopyingDataTreeBuilder::handle(SetNodeAccess const & _aNode)
{
sharable::SetNode const & aSrc = _aNode.data();
sharable::Name aNodeName = allocName( allocator(), aSrc.info.getName(_aNode.accessor()));
Flags::Field aFlags = aSrc.info.flags;
Address aTemplate = this->makeTemplateData(_aNode.accessor(), aSrc.elementType);
this->builder().addSet(aNodeName,aFlags,aTemplate);
OSL_ASSERT( this->builder().lastNode().isSet() );
SetNode& _aNewSet = this->builder().lastNode().set;
_aNewSet.elements = ElementListBuilder( this->updater() ).buildElementList(_aNode);
return CONTINUE;
}
//-----------------------------------------------------------------------------
Address CopyingDataTreeBuilder::makeTemplateData(Accessor const & _aSourceAccessor, Address _aSourceTemplate)
{
NameChar const * pTemplateName = SetNode::getTemplateDataName(_aSourceAccessor,_aSourceTemplate);
NameChar const * pTemplateModule = SetNode::getTemplateDataModule(_aSourceAccessor,_aSourceTemplate);
return SetNode::allocTemplateData(allocator(), pTemplateName, pTemplateModule );
}
//-----------------------------------------------------------------------------
List CopyingDataTreeBuilder::ElementListBuilder::buildElementList(SetNodeAccess const & _aSet)
{
OSL_PRECOND(_aSet.isValid(), "Node must not be NULL");
m_aCollector.resetElementList();
this->visitElements(_aSet);
return m_aCollector.getElementListAndClear();
}
//-----------------------------------------------------------------------------
NodeVisitor::Result CopyingDataTreeBuilder::ElementListBuilder::handle(TreeAccessor const & _aSourceTree)
{
TreeAddress aNewElement = CopyingDataTreeBuilder(m_aCollector.updater()).buildTree(_aSourceTree);
m_aCollector.addElement(aNewElement);
return CONTINUE;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
Name ConvertingDataTreeBuilder::allocName(INode const & _aNode)
{
rtl::OUString sNextName = _aNode.getName();
if (m_sRootName.getLength())
{
sNextName = m_sRootName;
m_sRootName = rtl::OUString();
}
return sharable::allocName( allocator(), sNextName);
}
//-----------------------------------------------------------------------------
TreeAddress ConvertingDataTreeBuilder::buildElement(INode const& _aNode, OUString const & _aTypeName, bool _bWithDefaults)
{
m_sRootName = _aTypeName;
m_bWithDefaults = _bWithDefaults;
sharable::String aTreeName = allocString( allocator(), _aNode.getName());
this->builder().resetTreeFragment(aTreeName, makeState(_aNode.getAttributes()));
this->applyToNode(_aNode);
return this->createTree();
}
//-----------------------------------------------------------------------------
TreeAddress ConvertingDataTreeBuilder::buildTree(OUString const & _aTreeName, INode const& _aNode, bool _bWithDefaults)
{
m_sRootName = OUString();
m_bWithDefaults = _bWithDefaults;
sharable::String aTreeName = allocString( allocator(), _aTreeName );
this->builder().resetTreeFragment(aTreeName, makeState(_aNode.getAttributes()));
this->applyToNode(_aNode);
return this->createTree();
}
//-----------------------------------------------------------------------------
void ConvertingDataTreeBuilder::handle(ISubtree const & _aNode)
{
sharable::Name aNodeName = allocName( _aNode );
Flags::Field aFlags = makeFlags(_aNode.getAttributes());
if (_aNode.isSetNode())
{
Address aTemplate = this->makeTemplateData(_aNode.getElementTemplateName(),_aNode.getElementTemplateModule());
this->builder().addSet(aNodeName,aFlags,aTemplate);
OSL_ASSERT( this->builder().lastNode().isSet() );
SetNode& _aNewSet = this->builder().lastNode().set;
_aNewSet.elements = ElementListBuilder(this->updater()).buildElementList(_aNode, m_bWithDefaults);
}
else
{
Offset nGroupOffset = this->builder().startGroup(aNodeName,aFlags);
this->applyToChildren(_aNode);
this->builder().endGroup(nGroupOffset);
}
}
//-----------------------------------------------------------------------------
void ConvertingDataTreeBuilder::handle(OValueNode const & _aNode)
{
sharable::Name aNodeName = allocName( _aNode );
Flags::Field aFlags = makeFlags(_aNode.getAttributes());
AnyData::TypeCode aType = getTypeCode(_aNode.getValueType());
AnyData aNewValue; aNewValue.data = 0;
AnyData aNewDefault; aNewDefault.data = 0;
OSL_ASSERT( !(aFlags & (Flags::valueAvailable | Flags::defaultAvailable)) );
if (!_aNode.isDefault())
{
uno::Any aValue = _aNode.getValue();
if (aValue.hasValue())
{
aNewValue = allocData(allocator(), aType, aValue);
aFlags |= Flags::valueAvailable;
}
}
if (_aNode.hasUsableDefault())
{
uno::Any aDefault = _aNode.getDefault();
if (aDefault.hasValue())
{
aNewDefault = allocData(allocator(), aType, aDefault);
aFlags |= Flags::defaultAvailable;
}
}
this->builder().addValue(aNodeName,aFlags,aType,aNewValue,aNewDefault);
}
//-----------------------------------------------------------------------------
State::Field ConvertingDataTreeBuilder::makeState(node::Attributes const & _aAttributes)
{
State::Field state;
switch (_aAttributes.state())
{
case node::isDefault: state = State::defaulted; m_bWithDefaults = true; break;
case node::isMerged: state = State::merged; break;
case node::isReplaced: state = State::replaced; m_bWithDefaults = false; break;
case node::isAdded: state = State::added; m_bWithDefaults = false; break;
default: OSL_ASSERT(false); state = 0; break;
}
if (!_aAttributes.bWritable)
state |= State::flag_readonly;
if ( m_bWithDefaults )
state |= State::flag_default_avail;
return state;
}
//-----------------------------------------------------------------------------
Flags::Field ConvertingDataTreeBuilder::makeFlags(node::Attributes const & _aAttributes)
{
Flags::Field flags = 0;
if (!_aAttributes.bWritable)
flags |= Flags::readonly;
if ( _aAttributes.bFinalized)
flags |= Flags::finalized;
if ( _aAttributes.bNullable)
flags |= Flags::nullable;
if ( _aAttributes.bLocalized)
flags |= Flags::localized;
if (_aAttributes.isDefault())
flags |= Flags::defaulted; // somewhat redundant with State
if (!_aAttributes.isReplacedForUser())
flags |= Flags::defaultable; // redundant with State (merged || defaulted)
return flags;
}
//-----------------------------------------------------------------------------
Address ConvertingDataTreeBuilder::makeTemplateData(rtl::OUString const & _aTemplateName, rtl::OUString const & _aTemplateModule)
{
NameChar const * pTemplateName = _aTemplateName.getStr();
NameChar const * pTemplateModule = _aTemplateModule.getStr();
return SetNode::allocTemplateData(allocator(), pTemplateName, pTemplateModule );
}
//-----------------------------------------------------------------------------
List ConvertingDataTreeBuilder::ElementListBuilder::buildElementList(ISubtree const & _aSet, bool _bWithDefaults)
{
OSL_PRECOND(_aSet.isSetNode(), "Node must be a set");
m_aCollector.resetElementList();
m_sTypeName = _aSet.getElementTemplateName();
m_bWithDefaults = _bWithDefaults;
this->applyToChildren(_aSet);
return m_aCollector.getElementListAndClear();
}
//-----------------------------------------------------------------------------
void ConvertingDataTreeBuilder::ElementListBuilder::handleNode(INode const & _aSourceNode)
{
TreeAddress aNewElement = ConvertingDataTreeBuilder(m_aCollector.updater())
.buildElement(_aSourceNode,m_sTypeName,m_bWithDefaults);
m_aCollector.addElement(aNewElement);
}
//-----------------------------------------------------------------------------
void ConvertingDataTreeBuilder::ElementListBuilder::handle(OValueNode const & _aSourceNode)
{
handleNode(_aSourceNode);
}
//-----------------------------------------------------------------------------
void ConvertingDataTreeBuilder::ElementListBuilder::handle(ISubtree const & _aSourceNode)
{
handleNode(_aSourceNode);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
std::auto_ptr<INode> ConvertingNodeBuilder::buildNode(TreeAccessor const & _aSourceTree, bool _bUseTreeName)
{
std::auto_ptr<INode> pResult = this->buildNode(_aSourceTree.getRootNode());
if (pResult.get() != NULL)
{
// use the element name !
if (_bUseTreeName) pResult->setName( _aSourceTree.getName().toString() );
// do something about attributes here ?
}
return pResult;
}
//-----------------------------------------------------------------------------
std::auto_ptr<INode> ConvertingNodeBuilder::buildNode(NodeAccess const & _aSourceNode)
{
OSL_ENSURE( !m_pNode.get(), "Old node tree will be dropped");
this->visitNode(_aSourceNode);
return m_pNode;
}
//-----------------------------------------------------------------------------
std::auto_ptr<ISubtree> ConvertingNodeBuilder::buildNodeTree(GroupNodeAccess const& _aGroupNode) const
{
std::auto_ptr<ISubtree> pResult = convertNode(_aGroupNode);
if (pResult.get() != NULL)
{
ConvertingSubnodeBuilder aCollector(m_rNodeFactory, *pResult);
aCollector.addChildren(_aGroupNode);
}
return pResult;
}
//-----------------------------------------------------------------------------
std::auto_ptr<ISubtree> ConvertingNodeBuilder::buildNodeTree(SetNodeAccess const& _aSetNode) const
{
std::auto_ptr<ISubtree> pResult = convertNode(_aSetNode);
if (pResult.get() != NULL)
{
ConvertingSubnodeBuilder aCollector(m_rNodeFactory, *pResult);
aCollector.addElements(_aSetNode);
}
return pResult;
}
//-----------------------------------------------------------------------------
std::auto_ptr<ISubtree> ConvertingNodeBuilder::convertNode(GroupNodeAccess const& _aGroupNode) const
{
return m_rNodeFactory.createGroupNode( _aGroupNode.getName().toString(),
convertAttributes(_aGroupNode));
}
//-----------------------------------------------------------------------------
std::auto_ptr<ISubtree> ConvertingNodeBuilder::convertNode(SetNodeAccess const& _aSetNode) const
{
return m_rNodeFactory.createSetNode(_aSetNode.getName().toString(),
_aSetNode.getElementTemplateName().toString(),
_aSetNode.getElementTemplateModule().toString(),
convertAttributes(_aSetNode));
}
//-----------------------------------------------------------------------------
std::auto_ptr<OValueNode> ConvertingNodeBuilder::convertNode(ValueNodeAccess const& _aValueNode) const
{
uno::Any aUserValue = _aValueNode.getUserValue();
uno::Any aDefValue = _aValueNode.getDefaultValue();
if (aUserValue.hasValue() || aDefValue.hasValue())
{
return m_rNodeFactory.createValueNode(_aValueNode.getName().toString(),
aUserValue, aDefValue,
convertAttributes(_aValueNode));
}
else
{
return m_rNodeFactory.createNullValueNode(_aValueNode.getName().toString(),
_aValueNode.getValueType(),
convertAttributes(_aValueNode));
}
}
//-----------------------------------------------------------------------------
NodeVisitor::Result ConvertingNodeBuilder::handle(ValueNodeAccess const & _aNode)
{
m_pNode = base_ptr(buildNodeTree(_aNode));
return DONE;
}
//-----------------------------------------------------------------------------
NodeVisitor::Result ConvertingNodeBuilder::handle(GroupNodeAccess const & _aNode)
{
m_pNode = base_ptr(buildNodeTree(_aNode));
return DONE;
}
//-----------------------------------------------------------------------------
NodeVisitor::Result ConvertingNodeBuilder::handle(SetNodeAccess const & _aNode)
{
m_pNode = base_ptr(buildNodeTree(_aNode));
return DONE;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
NodeVisitor::Result ConvertingSubnodeBuilder::handle(TreeAccessor const & _aElement)
{
OSL_ASSERT(m_rParentNode.isSetNode());
m_rParentNode.addChild( m_aSubnodeBuilder.buildNode(_aElement,true) );
return CONTINUE;
}
//-----------------------------------------------------------------------------
NodeVisitor::Result ConvertingSubnodeBuilder::handle(NodeAccess const & _aMember)
{
OSL_ASSERT(!m_rParentNode.isSetNode());
m_rParentNode.addChild( m_aSubnodeBuilder.buildNode(_aMember) );
return CONTINUE;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void DataTreeDefaultMerger::mergeDefaults(TreeAddress _aBaseAddress, INode const& _aDefaultNode)
{
}
//-----------------------------------------------------------------------------
void DataTreeDefaultMerger::handle(ISubtree const & _aNode)
{
}
//-----------------------------------------------------------------------------
void DataTreeDefaultMerger::handle(OValueNode const & _aNode)
{
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
TreeAddress DataTreeCleanup::destroyTree(TreeAddress _aBaseAddress)
{
TreeFragment * pData = TreeAccessor::access(_aBaseAddress,updater());
List aNext = pData->header.next;
Offset const nCount = pData->header.count;
destroyData( & pData->header );
for (Offset i = 0; i< nCount; ++i)
{
destroyNode( addressOfNodeAt(_aBaseAddress,i) );
}
allocator().deallocate( _aBaseAddress.addressValue() );
return TreeAddress( Pointer(aNext) );
}
//-----------------------------------------------------------------------------
void DataTreeCleanup::destroyNode(NodeAddress _aNodeAddress)
{
Node * pNode = NodeAccess::access(_aNodeAddress,updater());
Type::Field aTypeTag = pNode->node.info.type;
switch ( aTypeTag & Type::mask_nodetype )
{
case Type::nodetype_group:
destroyData( &pNode->group );
break;
case Type::nodetype_value:
destroyData( &pNode->value );
break;
case Type::nodetype_set:
destroyData( &pNode->set );
break;
default:
OSL_ENSURE(false, "Cannot destroy node: Invalid type tag in node");
break;
}
}
//-----------------------------------------------------------------------------
void DataTreeCleanup::destroyData(TreeFragmentHeader * _pHeader)
{
// 'component' is owned elsewhere -> leave alone
sharable::String aName = _pHeader->name;
freeString( allocator(), aName );
}
//-----------------------------------------------------------------------------
void DataTreeCleanup::destroyData(NodeInfo * _pNodeInfo)
{
Name aName = _pNodeInfo->name;
if (aName) freeName( allocator(), aName );
}
//-----------------------------------------------------------------------------
void DataTreeCleanup::destroyData(sharable::SetNode * _pNode)
{
TreeAddress aElement( Pointer( _pNode->elements ) );
Address aTemplate = _pNode->elementType;;
destroyData(&_pNode->info);
while (aElement.is())
aElement = destroyTree(aElement);
SetNode::releaseTemplateData( allocator(), aTemplate );
}
//-----------------------------------------------------------------------------
void DataTreeCleanup::destroyData(sharable::GroupNode * _pNode)
{
destroyData(&_pNode->info);
// nothing more to do
}
//-----------------------------------------------------------------------------
void DataTreeCleanup::destroyData(sharable::ValueNode * _pNode)
{
AnyData::TypeCode aValueType = _pNode->info.type & Type::mask_valuetype;
Flags::Field aFlags = _pNode->info.flags;
destroyData(&_pNode->info);
if (aFlags & Flags::valueAvailable)
freeData( allocator(), aValueType, _pNode->value );
if (aFlags & Flags::defaultAvailable)
freeData( allocator(), aValueType, _pNode->defaultValue );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-------------------------------------------------------------------------
}
//-----------------------------------------------------------------------------
} // namespace configmgr