/************************************************************************* * * $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 #define INCLUDED_CSTDDEF #endif #ifndef INCLUDED_ALGORITHM #include #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 m_pNode; public: ConvertingNodeBuilder(OTreeNodeFactory & _rNodeFactory) : m_rNodeFactory(_rNodeFactory) , m_pNode() { } std::auto_ptr buildNode(TreeAccessor const& _aTree, bool _bUseTreeName); std::auto_ptr buildNode(NodeAccess const& _aTree); std::auto_ptr buildNodeTree(GroupNodeAccess const& _aGroupNode) const; std::auto_ptr buildNodeTree(SetNodeAccess const& _aSetNode) const; std::auto_ptr buildNodeTree(ValueNodeAccess const& _aValueNode) const { return this->convertNode(_aValueNode); } static node::Attributes convertAttributes(NodeAccess const& _aNode) { return _aNode.getAttributes(); } private: std::auto_ptr convertNode(GroupNodeAccess const& _aGroupNode) const; std::auto_ptr convertNode(SetNodeAccess const& _aSetNode) const; std::auto_ptr 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 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ı 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(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 ConvertingNodeBuilder::buildNode(TreeAccessor const & _aSourceTree, bool _bUseTreeName) { std::auto_ptr 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 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 ConvertingNodeBuilder::buildNodeTree(GroupNodeAccess const& _aGroupNode) const { std::auto_ptr pResult = convertNode(_aGroupNode); if (pResult.get() != NULL) { ConvertingSubnodeBuilder aCollector(m_rNodeFactory, *pResult); aCollector.addChildren(_aGroupNode); } return pResult; } //----------------------------------------------------------------------------- std::auto_ptr ConvertingNodeBuilder::buildNodeTree(SetNodeAccess const& _aSetNode) const { std::auto_ptr pResult = convertNode(_aSetNode); if (pResult.get() != NULL) { ConvertingSubnodeBuilder aCollector(m_rNodeFactory, *pResult); aCollector.addElements(_aSetNode); } return pResult; } //----------------------------------------------------------------------------- std::auto_ptr ConvertingNodeBuilder::convertNode(GroupNodeAccess const& _aGroupNode) const { return m_rNodeFactory.createGroupNode( _aGroupNode.getName().toString(), convertAttributes(_aGroupNode)); } //----------------------------------------------------------------------------- std::auto_ptr ConvertingNodeBuilder::convertNode(SetNodeAccess const& _aSetNode) const { return m_rNodeFactory.createSetNode(_aSetNode.getName().toString(), _aSetNode.getElementTemplateName().toString(), _aSetNode.getElementTemplateModule().toString(), convertAttributes(_aSetNode)); } //----------------------------------------------------------------------------- std::auto_ptr 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