summaryrefslogtreecommitdiff
path: root/configmgr/source/treemgr/treeimpl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'configmgr/source/treemgr/treeimpl.cxx')
-rw-r--r--configmgr/source/treemgr/treeimpl.cxx1373
1 files changed, 1373 insertions, 0 deletions
diff --git a/configmgr/source/treemgr/treeimpl.cxx b/configmgr/source/treemgr/treeimpl.cxx
new file mode 100644
index 000000000000..66b26092e5e4
--- /dev/null
+++ b/configmgr/source/treemgr/treeimpl.cxx
@@ -0,0 +1,1373 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: treeimpl.cxx,v $
+ * $Revision: 1.33 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_configmgr.hxx"
+#include <stdio.h>
+#include "anynoderef.hxx"
+#include "builddata.hxx"
+#include "configset.hxx"
+#include "tracer.hxx"
+#include "tree.hxx"
+#include "roottreeimpl.hxx"
+#include "nodeimpl.hxx"
+#include "nodechange.hxx"
+#include "nodechangeimpl.hxx"
+#include "noderef.hxx"
+#include "template.hxx"
+#include "nodevisitor.hxx"
+#include "valueref.hxx"
+#include "valuenode.hxx"
+#include "change.hxx"
+#include "valuenodeimpl.hxx"
+#include "setnodeimpl.hxx"
+#include "groupnodeimpl.hxx"
+#include "viewaccess.hxx"
+#include "viewfactory.hxx"
+#include "nodefactory.hxx"
+#include <osl/diagnose.h>
+
+namespace configmgr
+{
+//-----------------------------------------------------------------------------
+ namespace configuration
+ {
+//-----------------------------------------------------------------------------
+// class TreeImplBuilder - friend of Tree
+//-----------------------------------------------------------------------------
+
+/** is a visitor-style algorithm to construct a <type>Tree::NodeList</type>
+ representing a configuration hierarchy
+*/
+class TreeImplBuilder : public data::NodeVisitor
+{
+public:
+ /** constructs a TreeImplBuilder to append onto <var>rList</var>
+ the products of <var>rFactory</var> up to depth <var>nDepth</var>
+ */
+ TreeImplBuilder(
+ TemplateProvider const& aTemplateProvider,
+ rtl::Reference<view::ViewStrategy> const& _xStrategy,
+ Tree& rTree
+ )
+ : m_xStrategy(_xStrategy)
+ , m_aTemplateProvider(aTemplateProvider)
+ , m_rFactory(_xStrategy->getNodeFactory())
+ , m_rTree(rTree)
+ , m_nParent(0)
+ , m_nDepthLeft(rTree.m_nDepth)
+ {
+ OSL_ASSERT(m_rTree.m_aNodes.empty());
+ OSL_DEBUG_ONLY(m_bMemberCheck = false);
+ m_rTree.m_xStrategy = _xStrategy;
+ }
+
+private:
+ using NodeVisitor::handle;
+
+ virtual bool handle(sharable::ValueNode * node);
+
+ virtual bool handle(sharable::GroupNode * node);
+
+ virtual bool handle(sharable::SetNode * node);
+
+ /// add a Node for group node <var>_aGroup</var> to the list
+ void addGroup(sharable::GroupNode * group);
+ /// add a Node for set node <var>_aSet</var> to the list
+ void addSet(sharable::SetNode * set);
+ /// add a Node for value node <var>rValue</var> to the list
+ void addValueElement(sharable::ValueNode * value);
+ /// add a Member for value node <var>rValue</var> to the list
+ void addValueMember(sharable::ValueNode * value);
+
+ rtl::Reference<view::ViewStrategy> m_xStrategy;
+ TemplateProvider m_aTemplateProvider;
+ view::NodeFactory& m_rFactory;
+ Tree& m_rTree;
+ unsigned int m_nParent;
+ unsigned int m_nDepthLeft;
+#if OSL_DEBUG_LEVEL > 0
+ bool m_bMemberCheck;
+#endif
+};
+//-----------------------------------------------------------------------------
+
+bool TreeImplBuilder::handle(sharable::ValueNode * node)
+{
+ if (m_nParent == 0)
+ addValueElement(node); // if it is the root it is a value set element
+ else
+ addValueMember(node); // if it is not the root it is a group member
+
+ return false;
+}
+//-----------------------------------------------------------------------------
+
+bool TreeImplBuilder::handle(sharable::GroupNode * node)
+{
+ addGroup(node);
+ return false;
+}
+//-----------------------------------------------------------------------------
+
+bool TreeImplBuilder::handle(sharable::SetNode * node)
+{
+ addSet(node);
+ return false;
+}
+//-----------------------------------------------------------------------------
+
+void TreeImplBuilder::addValueElement(sharable::ValueNode * value)
+{
+ rtl::Reference<NodeImpl> aValueNode( m_rFactory.makeValueNode(value) );
+ OSL_ENSURE( aValueNode.is(), "could not make value node wrapper" );
+
+ OSL_ENSURE( m_nParent == 0, "Adding value element that is not root of its fragment" );
+ // TODO:!isValid() => maybe substitute a SimpleValueNodeImpl if possible
+ if( aValueNode.is() )
+ {
+ m_rTree.m_aNodes.push_back( NodeData(aValueNode, value->info.getName(), m_nParent) );
+ }
+}
+//-----------------------------------------------------------------------------
+
+void TreeImplBuilder::addValueMember(sharable::ValueNode *)
+{
+ // nothing to do
+ OSL_DEBUG_ONLY(m_bMemberCheck = true);
+}
+//-----------------------------------------------------------------------------
+
+void TreeImplBuilder::addGroup(sharable::GroupNode * group)
+{
+ rtl::Reference<NodeImpl> aGroupNode( m_rFactory.makeGroupNode(group) );
+ OSL_ENSURE( aGroupNode.is(), "could not make group node wrapper" );
+
+ // TODO:!isValid() => maybe substitute a SimpleValueNodeImpl if possible
+ if( aGroupNode.is() )
+ {
+ m_rTree.m_aNodes.push_back( NodeData(aGroupNode,group->info.getName(),m_nParent) );
+
+ // now fill in group members
+ if (m_nDepthLeft > 0)
+ {
+ unsigned int nSaveParent = m_nParent;
+ decDepth(m_nDepthLeft);
+
+ m_nParent = m_rTree.m_aNodes.size() + Tree::ROOT - 1;
+
+ #if OSL_DEBUG_LEVEL > 0
+ bool bSaveMemberCheck = m_bMemberCheck;
+ m_bMemberCheck = false;
+ #endif
+
+ // now recurse:
+ this->visitChildren(group);
+
+ 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);
+
+ incDepth(m_nDepthLeft);
+ m_nParent = nSaveParent;
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+
+void TreeImplBuilder::addSet(sharable::SetNode * set)
+{
+ rtl::Reference<Template> aTemplate = makeSetElementTemplate(set, m_aTemplateProvider);
+ OSL_ASSERT(aTemplate.is());
+ OSL_ENSURE(aTemplate->isInstanceTypeKnown(),"ERROR: Cannor create set instance without knowing the instance type");
+
+ rtl::Reference<NodeImpl> aSetNode( m_rFactory.makeSetNode(set, aTemplate.get()) );
+ OSL_ENSURE( aSetNode.is(), "could not make set node wrapper" );
+
+ // TODO:!isValid() => maybe substitute a SimpleValueNodeImpl if possible
+ if( aSetNode.is() )
+ {
+ m_rTree.m_aNodes.push_back( NodeData(aSetNode, set->info.getName(), m_nParent) );
+
+ // this also relies on one based offsets
+ unsigned int nNodeAdded = m_rTree.m_aNodes.size() + Tree::ROOT - 1;
+
+ OSL_ASSERT(&m_rTree.m_aNodes.back().nodeImpl() == aSetNode.get());
+ static_cast<SetNodeImpl&>(*aSetNode).initElements(m_aTemplateProvider, m_rTree, nNodeAdded, m_nDepthLeft);
+ }
+}
+
+namespace {
+ class FindNonDefaultElement: public SetNodeVisitor {
+ public:
+ static bool hasNonDefaultElement(
+ view::ViewTreeAccess const & view, view::SetNode const & set)
+ {
+ FindNonDefaultElement visitor;
+ return view.dispatchToElements(set, visitor) == DONE;
+ }
+
+ protected:
+ virtual Result visit(SetEntry const & entry) {
+ OSL_ASSERT(entry.isValid());
+ rtl::Reference< Tree > tree(entry.tree());
+ OSL_ASSERT(tree.is());
+ node::Attributes atts(tree->getAttributes(tree->getRootNode()));
+ // A set element is considered default iff it is not replaced/added:
+ bool dflt = !atts.isReplacedForUser();
+ return dflt ? CONTINUE : DONE;
+ }
+ };
+
+ class SetVisitorAdapter: public SetNodeVisitor {
+ public:
+ explicit SetVisitorAdapter(NodeVisitor & visitor): m_visitor(visitor) {}
+
+ protected:
+ virtual Result visit(SetEntry const & entry) {
+ OSL_ASSERT(entry.isValid());
+ rtl::Reference< Tree > tree(entry.tree());
+ if (tree.is()) {
+ OSL_ASSERT(
+ Result(NodeVisitor::DONE) == SetNodeVisitor::DONE &&
+ Result(NodeVisitor::CONTINUE) == SetNodeVisitor::CONTINUE);
+ return Result(tree->visit(tree->getRootNode(), m_visitor));
+ } else {
+ return CONTINUE;
+ }
+ }
+
+ private:
+ NodeVisitor & m_visitor;
+ };
+
+ class GroupVisitorAdapter: public GroupMemberVisitor {
+ public:
+ GroupVisitorAdapter(
+ rtl::Reference< Tree > const & parentTree,
+ NodeRef const & parentNode, NodeVisitor & visitor):
+ m_parentTree(parentTree), m_parentPos(parentNode.getOffset()),
+ m_visitor(visitor)
+ {
+ OSL_ASSERT(
+ !isEmpty(parentTree.get()) && parentNode.isValid() &&
+ parentTree->isValidNode(parentNode.getOffset()));
+ }
+
+ protected:
+ virtual Result visit(ValueMemberNode const & value) {
+ OSL_ASSERT(
+ value.isValid() &&
+ Result(NodeVisitor::DONE) == GroupMemberVisitor::DONE &&
+ Result(NodeVisitor::CONTINUE) == GroupMemberVisitor::CONTINUE);
+ return Result(
+ m_parentTree->visit(
+ ValueRef(value.getNodeName(), m_parentPos), m_visitor));
+ }
+
+ private:
+ rtl::Reference< Tree > m_parentTree;
+ unsigned int m_parentPos;
+ NodeVisitor & m_visitor;
+ };
+}
+
+//-----------------------------------------------------------------------------
+// class NodeData
+//-----------------------------------------------------------------------------
+
+NodeData::NodeData(rtl::Reference<NodeImpl> const& aSpecificNode, rtl::OUString const& aName, unsigned int nParent)
+: m_pSpecificNode(aSpecificNode)
+, m_aName_(aName)
+, m_nParent(nParent)
+{
+}
+
+//-----------------------------------------------------------------------------
+
+void NodeData::rebuild(rtl::Reference<view::ViewStrategy> const & _xNewStrategy, sharable::Node * newData)
+{
+ rtl::Reference<NodeImpl> aNewImpl;
+ if (this->isSetNode())
+ {
+ sharable::SetNode * newSet = newData == 0 ? 0 : newData->setData();
+ aNewImpl = _xNewStrategy->getNodeFactory().makeSetNode(newSet, 0);
+
+ SetNodeImpl & rOldSetData = this->setImpl();
+ SetNodeImpl & rNewSetData = static_cast<SetNodeImpl &>(*aNewImpl);
+
+ rNewSetData.rebuildFrom(rOldSetData, newSet);
+ }
+ else if (this->isGroupNode())
+ aNewImpl = _xNewStrategy->getNodeFactory().makeGroupNode(newData == 0 ? 0 : newData->groupData());
+
+ else if (this->isValueElementNode())
+ aNewImpl = _xNewStrategy->getNodeFactory().makeValueNode(newData == 0 ? 0 : newData->valueData());
+
+ m_pSpecificNode = aNewImpl;
+}
+
+//-----------------------------------------------------------------------------
+
+bool NodeData::isSetNode() const
+{
+ sharable::Node * node = getOriginalNodeAccess();
+ return node != 0 && node->isSet();
+}
+//-----------------------------------------------------------------------------
+
+bool NodeData::isValueElementNode() const
+{
+ sharable::Node * node = getOriginalNodeAccess();
+ return node != 0 && node->isValue();
+}
+//-----------------------------------------------------------------------------
+
+bool NodeData::isGroupNode() const
+{
+ sharable::Node * node = getOriginalNodeAccess();
+ return node != 0 && node->isGroup();
+}
+//-----------------------------------------------------------------------------
+
+SetNodeImpl& NodeData::implGetSetImpl() const
+{
+ OSL_ASSERT(m_pSpecificNode != 0);
+ OSL_ASSERT(isSetNode());
+
+ if (!isSetNode())
+ throw Exception( "INTERNAL ERROR: Node is not a set node. Cast failing." );
+
+ return static_cast<SetNodeImpl&>(*m_pSpecificNode);
+}
+//---------------------------------------------------------------------
+
+GroupNodeImpl& NodeData::implGetGroupImpl() const
+{
+ OSL_ASSERT(m_pSpecificNode != 0);
+ OSL_ASSERT(isGroupNode());
+
+ if (!isGroupNode())
+ throw Exception( "INTERNAL ERROR: Node is not a group node. Cast failing." );
+
+ return static_cast<GroupNodeImpl&>(*m_pSpecificNode);
+}
+//---------------------------------------------------------------------
+
+ValueElementNodeImpl& NodeData::implGetValueImpl() const
+{
+ OSL_ASSERT(m_pSpecificNode != 0);
+ OSL_ASSERT(isValueElementNode());
+
+ if (!isValueElementNode())
+ throw Exception( "INTERNAL ERROR: Node is not a value node. Cast failing." );
+
+ return static_cast<ValueElementNodeImpl&>(*m_pSpecificNode);
+}
+
+sharable::Node * NodeData::getOriginalNodeAccess() const
+{
+ return m_pSpecificNode->getOriginalNodeAccess();
+}
+
+NodeImpl & NodeData::implGetNodeImpl() const
+{
+ OSL_ASSERT(m_pSpecificNode != 0);
+ return *m_pSpecificNode;
+}
+
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// class Tree
+//-----------------------------------------------------------------------------
+
+/// creates a Tree for a detached, virgin instance of <var>aTemplate</var>
+Tree::Tree( )
+: m_aNodes()
+, m_pParentTree(0)
+, m_nParentNode(0)
+, m_nDepth(0)
+{
+}
+//-----------------------------------------------------------------------------
+
+Tree::Tree( Tree& rParentTree, unsigned int nParentNode )
+: m_aNodes()
+, m_pParentTree(&rParentTree)
+, m_nParentNode(nParentNode)
+, m_nDepth(0)
+{
+}
+//-----------------------------------------------------------------------------
+
+Tree::~Tree()
+{
+}
+//-----------------------------------------------------------------------------
+
+void Tree::disposeData()
+{
+ m_aNodes.clear();
+}
+
+bool Tree::isRootNode(NodeRef const & node) const {
+ OSL_ASSERT(
+ nodeCount() != 0 && (!node.isValid() || isValidNode(node.getOffset())));
+ return node.isValid() && node.getOffset() == ROOT;
+}
+
+NodeRef Tree::getRootNode() const {
+ OSL_ASSERT(nodeCount() != 0);
+ return NodeRef(ROOT, m_nDepth);
+}
+
+NodeRef Tree::getContextNodeRef() const {
+ OSL_ASSERT(nodeCount() != 0 && (m_pParentTree == 0 || m_nParentNode != 0));
+ return m_pParentTree == 0
+ ? NodeRef() : m_pParentTree->getNode(m_nParentNode);
+}
+
+bool Tree::isValidValueNode(ValueRef const & value) {
+ OSL_ASSERT(nodeCount() != 0);
+ if (!(value.isValid() &&
+ value.checkValidState() &&
+ isValidNode(value.m_nParentPos) &&
+ view::ViewTreeAccess(this).isGroupNodeAt(value.m_nParentPos) &&
+ getMemberNode(value).isValid()))
+ {
+ return false;
+ }
+ OSL_ASSERT(value.m_sNodeName.getLength() != 0); // old value handling?
+ return true;
+}
+
+#if OSL_DEBUG_LEVEL > 0
+bool Tree::isValidAnyNode(AnyNodeRef const & node) {
+ OSL_ASSERT(nodeCount() != 0);
+ return node.isValid() && isValidNode(node.m_nUsedPos) &&
+ (node.isNode() ||
+ (view::ViewTreeAccess(this).isGroupNodeAt(node.m_nUsedPos) &&
+ getMemberNode(node.toValue()).isValid()));
+}
+#endif
+
+bool Tree::hasElements(NodeRef const & node) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ if (node.getDepth() == 0) {
+ CFG_TRACE_WARNING(
+ "configuration: Querying node beyond available depth" );
+ }
+ view::ViewTreeAccess v(this);
+ return v.isSetNode(node) && !v.isEmpty(v.toSetNode(node));
+}
+
+bool Tree::hasElement(NodeRef const & node, rtl::OUString const & name) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ if (node.getDepth() == 0) {
+ CFG_TRACE_WARNING(
+ "configuration: Querying node beyond available depth");
+ }
+ view::ViewTreeAccess v(this);
+ return v.isSetNode(node) &&
+ v.findElement(v.toSetNode(node), name).isValid();
+}
+
+bool Tree::hasElement(NodeRef const & node, Path::Component const & name) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ if (node.getDepth() == 0) {
+ CFG_TRACE_WARNING(
+ "configuration: Querying node beyond available depth");
+ }
+ view::ViewTreeAccess v(this);
+ if (v.isSetNode(node)) {
+ SetEntry e(v.findElement(v.toSetNode(node), name.getName()));
+ // Check if types match:
+ return e.isValid() &&
+ Path::matches(e.tree()->getExtendedRootName(), name);
+ } else {
+ return false;
+ }
+}
+
+rtl::Reference< ElementTree > Tree::getElement(NodeRef const & node, rtl::OUString const & name) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ if (node.getDepth() == 0) {
+ CFG_TRACE_WARNING(
+ "configuration: Querying node beyond available depth");
+ }
+ view::ViewTreeAccess v(this);
+ if (v.isSetNode(node)) {
+ SetEntry e(v.findElement(v.toSetNode(node), name));
+ return rtl::Reference< ElementTree >(e.tree());
+ } else {
+ return rtl::Reference< ElementTree >();
+ }
+}
+
+rtl::Reference< ElementTree > Tree::getAvailableElement(
+ NodeRef const & node, rtl::OUString const & name)
+{
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ view::ViewTreeAccess v(this);
+ if (v.isSetNode(node)) {
+ SetEntry e(v.findAvailableElement(v.toSetNode(node), name));
+ return rtl::Reference< ElementTree >(e.tree());
+ } else {
+ return rtl::Reference< ElementTree >();
+ }
+}
+
+bool Tree::hasChildren(NodeRef const & node) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ if (node.getDepth() == 0) {
+ CFG_TRACE_WARNING(
+ "configuration: Querying node beyond available depth");
+ }
+ view::ViewTreeAccess v(this);
+ if (v.isGroupNode(node)) {
+ view::GroupNode g(v.toGroupNode(node));
+ return v.hasValue(g) || g.getFirstChild().is();
+ } else {
+ return false;
+ }
+}
+
+bool Tree::hasChildValue(NodeRef const & node, rtl::OUString const & name) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ if (node.getDepth() == 0) {
+ CFG_TRACE_WARNING(
+ "configuration: Querying node beyond available depth");
+ }
+ view::ViewTreeAccess v(this);
+ return v.isGroupNode(node) && v.hasValue(v.toGroupNode(node), name);
+}
+
+bool Tree::hasChildNode(NodeRef const & node, rtl::OUString const & name) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ if (node.getDepth() == 0) {
+ CFG_TRACE_WARNING(
+ "configuration: Querying node beyond available depth");
+ }
+ view::ViewTreeAccess v(this);
+ return v.isGroupNode(node) && v.toGroupNode(node).findChild(name).is();
+}
+
+bool Tree::hasChild(NodeRef const & node, rtl::OUString const & name) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ if (node.getDepth() == 0) {
+ CFG_TRACE_WARNING(
+ "configuration: Querying node beyond available depth");
+ }
+ view::ViewTreeAccess v(this);
+ if (v.isGroupNode(node)) {
+ view::GroupNode g(v.toGroupNode(node));
+ return v.hasValue(g, name) || g.findChild(name).is();
+ } else {
+ return false;
+ }
+}
+
+ValueRef Tree::getChildValue(NodeRef const & node, rtl::OUString const & name) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ if (node.getDepth() == 0) {
+ CFG_TRACE_WARNING(
+ "configuration: Querying node beyond available depth");
+ }
+ view::ViewTreeAccess v(this);
+ return v.isGroupNode(node) && v.hasValue(v.toGroupNode(node), name)
+ ? ValueRef(name, node.getOffset()) : ValueRef();
+}
+
+NodeRef Tree::getChildNode(NodeRef const & node, rtl::OUString const & name)
+{
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ if (node.getDepth() == 0) {
+ CFG_TRACE_WARNING(
+ "configuration: Querying node beyond available depth");
+ }
+ view::ViewTreeAccess v(this);
+ return NodeRef(
+ (v.isGroupNode(node)
+ ? v.toGroupNode(node).findChild(name).get_offset() : 0),
+ childDepth(node.getDepth()));
+}
+
+AnyNodeRef Tree::getAnyChild(NodeRef const & node, rtl::OUString const & name) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ if (node.getDepth() == 0) {
+ CFG_TRACE_WARNING(
+ "configuration: Querying node beyond available depth");
+ }
+ view::ViewTreeAccess v(this);
+ unsigned int n = 0;
+ if (v.isGroupNode(node)) {
+ if (v.hasValue(v.toGroupNode(node), name)) {
+ return AnyNodeRef(name, node.getOffset());
+ }
+ n = v.toGroupNode(node).findChild(name).get_offset();
+ }
+ return AnyNodeRef(n, childDepth(node.getDepth()));
+}
+
+node::Attributes Tree::getAttributes(NodeRef const & node) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ return view::ViewTreeAccess(this).getAttributes(node);
+}
+
+node::Attributes Tree::getAttributes(AnyNodeRef const & node) {
+ OSL_ASSERT(nodeCount() != 0 && isValidAnyNode(node));
+ if (node.isNode()) {
+ return view::ViewTreeAccess(this).getAttributes(node.toNode());
+ } else {
+ return getMemberNode(node.toValue()).getAttributes();
+ }
+}
+
+node::Attributes Tree::getAttributes(ValueRef const & value) {
+ OSL_ASSERT(nodeCount() != 0 && isValidValueNode(value));
+ return getMemberNode(value).getAttributes();
+}
+
+com::sun::star::uno::Type Tree::getUnoType(ValueRef const & value) {
+ OSL_ASSERT(nodeCount() != 0 && isValidValueNode(value));
+ return getMemberNode(value).getValueType();
+}
+
+NodeRef Tree::getParent(NodeRef const & node) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ view::ViewTreeAccess v(this);
+ OSL_ASSERT(!v.makeNode(getRootNode()).getParent().is());
+ view::Node p(v.makeNode(node).getParent());
+ OSL_ASSERT(isValidNode(p.get_offset()));
+ return NodeRef(p.get_offset(), parentDepth(node.getDepth()));
+}
+
+NodeRef Tree::getParent(ValueRef const & value) {
+ OSL_ASSERT(nodeCount() != 0 && isValidValueNode(value));
+ unsigned int n = value.m_nParentPos;
+ OSL_ASSERT(n == 0 || value.m_sNodeName.getLength() != 0);
+ return getNode(n);
+}
+
+AbsolutePath Tree::getAbsolutePath(NodeRef const & node) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ Path::Rep r;
+ prependLocalPathTo(node.getOffset(), r);
+ r.prepend(getRootPath().rep());
+ return AbsolutePath(r);
+}
+
+com::sun::star::uno::Any Tree::getNodeValue(ValueRef const & value) {
+ OSL_ASSERT(isValidValueNode(value));
+ return getMemberNode(value).getValue();
+}
+
+bool Tree::hasNodeDefault(ValueRef const & value) {
+ OSL_ASSERT(nodeCount() != 0 && isValidValueNode(value));
+ return getMemberNode(value).canGetDefaultValue();
+}
+
+bool Tree::isNodeDefault(ValueRef const & value) {
+ OSL_ASSERT(nodeCount() != 0 && isValidValueNode(value));
+ return hasNodeDefault(value) && getMemberNode(value).isDefault();
+}
+
+bool Tree::hasNodeDefault(NodeRef const & node) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ // Not a set, then it has no default:
+ return view::ViewTreeAccess(this).isSetNode(node);
+}
+
+bool Tree::isNodeDefault(NodeRef const & node) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ if (!hasNodeDefault(node)) {
+ return false;
+ }
+ view::ViewTreeAccess v(this);
+ OSL_ASSERT(v.isSetNode(node)); // not a set, then it has no default
+ // A set is default if all its elements are default:
+ return !FindNonDefaultElement::hasNonDefaultElement(v, v.toSetNode(node));
+}
+
+bool Tree::hasNodeDefault(AnyNodeRef const & node) {
+ OSL_ASSERT(nodeCount() != 0 && isValidAnyNode(node));
+ return node.isNode()
+ ? hasNodeDefault(node.toNode()) : hasNodeDefault(node.toValue());
+}
+
+bool Tree::isNodeDefault(AnyNodeRef const & node) {
+ OSL_ASSERT(nodeCount() != 0 && isValidAnyNode(node));
+ return node.isNode()
+ ? isNodeDefault(node.toNode()) : isNodeDefault(node.toValue());
+}
+
+bool Tree::areValueDefaultsAvailable(NodeRef const & node) {
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ view::ViewTreeAccess v(this);
+ OSL_ASSERT(v.isGroupNode(node));
+ return v.isGroupNode(node) &&
+ v.areValueDefaultsAvailable(v.toGroupNode(node));
+}
+
+com::sun::star::uno::Any Tree::getNodeDefaultValue(ValueRef const & value) {
+ OSL_ASSERT(nodeCount() != 0 && isValidValueNode(value));
+ ValueMemberNode m(getMemberNode(value));
+ return m.canGetDefaultValue() ?
+ m.getDefaultValue() : com::sun::star::uno::Any();
+}
+
+bool Tree::hasChanges() {
+ return view::ViewTreeAccess(this).hasChanges();
+}
+
+bool Tree::collectChanges(NodeChanges & changes) {
+ OSL_ASSERT(nodeCount() != 0);
+ view::ViewTreeAccess v(this);
+ if (v.hasChanges()) {
+ v.collectChanges(changes);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void Tree::integrate(NodeChange & change, NodeRef const & node, bool local)
+{
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ if (change.test().isChange()) {
+ change.apply();
+ if (local) {
+ view::ViewTreeAccess(this).markChanged(node);
+ } else {
+ rtl::Reference< Tree > at(change.getAffectedTree());
+ NodeRef an(change.getAffectedNode());
+ OSL_ASSERT(
+ !isEmpty(at.get()) && an.isValid() &&
+ at->isValidNode(an.getOffset()));
+ view::ViewTreeAccess(at.get()).markChanged(an);
+ OSL_ASSERT(view::ViewTreeAccess(this).hasChanges());
+ }
+ }
+}
+
+void Tree::integrate(NodeChanges& changes, NodeRef const & node, bool local)
+{
+ for (std::vector< NodeChange >::iterator it(changes.begin());
+ it != changes.end(); ++it)
+ {
+ integrate(*it, node, local);
+ }
+}
+
+NodeVisitor::Result Tree::dispatchToChildren(
+ NodeRef const & node, NodeVisitor & visitor)
+{
+ OSL_ASSERT(
+ nodeCount() != 0 && node.isValid() && isValidNode(node.getOffset()));
+ if (node.getDepth() == 0) {
+ CFG_TRACE_WARNING(
+ "configuration: Querying node beyond available depth");
+ }
+ view::ViewTreeAccess v(this);
+ if (v.isGroupNode(node)) {
+ view::GroupNode const p(v.toGroupNode(node));
+ OSL_ASSERT(
+ (NodeVisitor::Result(GroupMemberVisitor::DONE) ==
+ NodeVisitor::DONE) &&
+ (NodeVisitor::Result(GroupMemberVisitor::CONTINUE) ==
+ NodeVisitor::CONTINUE));
+ GroupVisitorAdapter adapter(this, node, visitor);
+ NodeVisitor::Result ret = NodeVisitor::Result(
+ v.dispatchToValues(p, adapter));
+ unsigned int n = childDepth(node.getDepth());
+ for (view::Node c(p.getFirstChild());
+ c.is() && ret != NodeVisitor::DONE; c = p.getNextChild(c))
+ {
+ ret = visit(NodeRef(c.get_offset(), n), visitor);
+ }
+ return ret;
+ } else if (v.isSetNode(node)) {
+ OSL_ASSERT(
+ NodeVisitor::Result(SetNodeVisitor::DONE) == NodeVisitor::DONE &&
+ (NodeVisitor::Result(SetNodeVisitor::CONTINUE) ==
+ NodeVisitor::CONTINUE));
+ SetVisitorAdapter adapter(visitor);
+ return NodeVisitor::Result(
+ v.dispatchToElements(v.toSetNode(node), adapter));
+ } else {
+ OSL_TRACE("configuration: Trying to iterate a value node");
+ return NodeVisitor::CONTINUE;
+ }
+}
+
+NodeRef Tree::getNode(unsigned int offset) const {
+ if (offset == 0) {
+ return NodeRef();
+ } else {
+ OSL_ASSERT(isValidNode(offset));
+ return NodeRef(
+ offset, remainingDepth(getAvailableDepth(), depthTo(offset)));
+ }
+}
+
+rtl::Reference< Template > Tree::extractElementInfo(NodeRef const & node) {
+ OSL_ASSERT(node.isValid() && isValidNode(node.getOffset()));
+ view::ViewTreeAccess v(this);
+ OSL_ASSERT(v.isSetNode(node));
+ return v.getElementTemplate(v.toSetNode(node));
+}
+
+//-----------------------------------------------------------------------------
+void Tree::rebuild(rtl::Reference<view::ViewStrategy> const & _xNewStrategy, sharable::Node * newData)
+{
+ m_xStrategy = _xNewStrategy;
+ this->implRebuild(ROOT, newData);
+}
+
+//-----------------------------------------------------------------------------
+void Tree::implRebuild(unsigned int nNode, sharable::Node * newData)
+{
+ NodeData * pNode = nodeData(nNode);
+ if (pNode->isGroupNode())
+ {
+ // first rebuild the children
+ OSL_ASSERT(newData != 0 && newData->isGroup());
+ sharable::GroupNode * newGroup = &newData->group;
+
+ for (unsigned int nChild = firstChild_(nNode); isValidNode(nChild); nChild = findNextChild_(nNode,nChild))
+ {
+ sharable::Node * childAccess = newGroup->getChild(implGetOriginalName(nChild));
+ OSL_ASSERT(childAccess != 0);
+ implRebuild(nChild, childAccess);
+ }
+ }
+
+ pNode->rebuild(m_xStrategy, newData);
+}
+
+//-----------------------------------------------------------------------------
+
+void ElementTree::doFinishRootPath(Path::Rep& rPath) const
+{
+ rPath.prepend( doGetRootName() );
+ rPath.prepend( AbsolutePath::detachedRoot().rep() );
+}
+//-----------------------------------------------------------------------------
+
+void RootTree::doFinishRootPath(Path::Rep& rPath) const
+{
+ rPath.prepend( m_aRootPath.rep() );
+}
+
+//-----------------------------------------------------------------------------
+
+void Tree::implPrependRootPath(Path::Rep& rPath) const
+{
+ if (m_pParentTree)
+ {
+ rPath.prepend( doGetRootName() );
+ OSL_ASSERT(m_nParentNode);
+ m_pParentTree->prependLocalPathTo(m_nParentNode,rPath);
+ m_pParentTree->implPrependRootPath(rPath);
+ }
+ else
+ {
+ doFinishRootPath( rPath );
+ }
+}
+//-----------------------------------------------------------------------------
+
+AbsolutePath Tree::getRootPath() const
+{
+ Path::Rep aPath;
+ implPrependRootPath(aPath);
+ return AbsolutePath(aPath);
+}
+//-----------------------------------------------------------------------------
+void Tree::build(rtl::Reference<view::ViewStrategy> const& _xStrategy, sharable::Node * rootNode, unsigned int nDepth, TemplateProvider const& aTemplateProvider)
+{
+ OSL_ASSERT(m_aNodes.empty());
+ m_nDepth = nDepth;
+ TreeImplBuilder a(aTemplateProvider, _xStrategy,*this);
+ a.visitNode(rootNode);
+}
+//-----------------------------------------------------------------------------
+
+rtl::Reference< view::ViewStrategy > Tree::getViewBehavior() const
+{
+ return m_xStrategy;
+}
+
+// context handling
+//-----------------------------------------------------------------------------
+
+void Tree::setContext(Tree* pParentTree, unsigned int 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->isSetNodeAt(nParentNode),"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 Tree::clearContext()
+{
+ m_pParentTree = 0;
+ m_nParentNode = 0;
+}
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Node Collection navigation
+//-----------------------------------------------------------------------------
+
+unsigned int Tree::parent_(unsigned int nNode) const
+{
+ OSL_ASSERT(isValidNode(nNode));
+ return nodeData(nNode)->getParent();
+}
+//-----------------------------------------------------------------------------
+inline // is protected and should be used only here
+rtl::OUString Tree::implGetOriginalName(unsigned int nNode) const
+{
+ OSL_ASSERT(isValidNode(nNode));
+
+ return nodeData(nNode)->getName();
+}
+//-----------------------------------------------------------------------------
+
+Path::Component ElementTree::doGetRootName() const
+{
+ return makeExtendedName( m_aElementName );
+}
+
+//-----------------------------------------------------------------------------
+
+rtl::OUString ElementTree::getSimpleRootName() const
+{
+ // Tree::getSimpleRootName tends to parse &
+ // then split the same name, burning CPU L&R
+ return m_aElementName;
+}
+
+//-----------------------------------------------------------------------------
+
+Path::Component RootTree::doGetRootName() const
+{
+ return m_aRootPath.getLocalName();
+}
+//-----------------------------------------------------------------------------
+
+
+rtl::OUString Tree::getSimpleNodeName(unsigned int nNode) const
+{
+ if (nNode == ROOT) return getSimpleRootName();
+
+ return implGetOriginalName(nNode);
+}
+//-----------------------------------------------------------------------------
+
+rtl::OUString Tree::getSimpleRootName() const
+{
+ return doGetRootName().getName();
+}
+
+//-----------------------------------------------------------------------------
+
+Path::Component Tree::getExtendedRootName() const
+{
+ return doGetRootName();
+}
+//-----------------------------------------------------------------------------
+
+unsigned int Tree::depthTo(unsigned int nNode) const
+{
+ OSL_ASSERT(isValidNode(nNode));
+
+ unsigned int nDepth = 0;
+ while( 0 != (nNode=parent_(nNode)) )
+ {
+ ++nDepth;
+ }
+
+ return nDepth;
+}
+//-----------------------------------------------------------------------------
+
+void Tree::prependLocalPathTo(unsigned int nNode, Path::Rep& rNames)
+{
+ OSL_ASSERT(isValidNode(nNode));
+
+ for (; nNode != ROOT; nNode = parent_(nNode) )
+ {
+ OSL_ENSURE( isValidNode(nNode), "ERROR: Configuration: node has invalid parent");
+ rNames.prepend( Path::wrapSimpleName( implGetOriginalName(nNode) ) );
+ }
+
+ OSL_ASSERT(nNode == ROOT);
+}
+//-----------------------------------------------------------------------------
+
+// Node iteration and access
+unsigned int Tree::firstChild_ (unsigned int nParent) const
+{
+ return findNextChild_(nParent,nParent);
+}
+//-----------------------------------------------------------------------------
+
+unsigned int Tree::findNextChild_(unsigned int nParent, unsigned int nStartAfter) const
+{
+ OSL_ASSERT(isValidNode(nParent));
+ OSL_ASSERT(nStartAfter == 0 || isValidNode(nStartAfter));
+
+ unsigned int nPos = nStartAfter ? nStartAfter : ROOT - 1;
+ unsigned int const nAfterLast = nodeCount() + ROOT;
+ while (++nPos < nAfterLast)
+ {
+ if(parent_(nPos) == nParent) return nPos;
+ }
+ return 0;
+}
+//-----------------------------------------------------------------------------
+
+unsigned int Tree::findChild_(unsigned int nParent, rtl::OUString const& aName) const
+{
+ OSL_ASSERT(isValidNode(nParent));
+
+ unsigned int nPos = nParent;
+ unsigned int const nAfterLast = nodeCount() + ROOT;
+ while (++nPos < nAfterLast)
+ {
+ if(parent_(nPos) == nParent && implGetOriginalName(nPos) == aName)
+ return nPos;
+ }
+ return 0;
+}
+
+ValueMemberNode Tree::getMemberNode(ValueRef const & value) {
+ OSL_ASSERT(nodeCount() != 0);
+ view::ViewTreeAccess v(this);
+ return v.getValue(v.getGroupNodeAt(value.m_nParentPos), value.m_sNodeName);
+}
+
+//-----------------------------------------------------------------------------
+// class RootTree
+//-----------------------------------------------------------------------------
+
+RootTree::RootTree( rtl::Reference<view::ViewStrategy> const& _xStrategy,
+ AbsolutePath const& aRootPath,
+ sharable::Node * cacheNode, unsigned int nDepth,
+ TemplateProvider const& aTemplateProvider)
+: Tree()
+, m_aRootPath(aRootPath)
+{
+// OSL_ENSURE( aRootPath.getLocalName().getName() == cacheNode->getName(),
+// "Constructing root node: Path does not match node name");
+
+ Tree::build(_xStrategy,cacheNode,nDepth,aTemplateProvider);
+}
+
+bool isEmpty(Tree * tree)
+{
+ return tree == 0 || tree->nodeCount() == 0;
+}
+
+//-----------------------------------------------------------------------------
+// class ElementTree
+//-----------------------------------------------------------------------------
+
+ElementTree::ElementTree( rtl::Reference<view::ViewStrategy> const& _xStrategy,
+ sharable::TreeFragment * cacheTree, unsigned int nDepth,
+ rtl::Reference<Template> aTemplateInfo,
+ TemplateProvider const& aTemplateProvider )
+: Tree()
+, m_aInstanceInfo(aTemplateInfo)
+, m_aElementName(cacheTree->getName())
+, m_aDataAddress(cacheTree)
+, m_aOwnData()
+{
+ Tree::build( _xStrategy, cacheTree->getRootNode(), nDepth, aTemplateProvider );
+}
+//-----------------------------------------------------------------------------
+
+ElementTree::ElementTree( rtl::Reference<view::ViewStrategy> const& _xStrategy,
+ Tree& rParentTree, unsigned int nParentNode,
+ sharable::TreeFragment * cacheTree, unsigned int nDepth,
+ rtl::Reference<Template> aTemplateInfo,
+ TemplateProvider const& aTemplateProvider )
+: Tree( rParentTree, nParentNode )
+, m_aInstanceInfo(aTemplateInfo)
+, m_aElementName(cacheTree->getName())
+, m_aDataAddress(cacheTree)
+, m_aOwnData()
+{
+ Tree::build( _xStrategy, cacheTree->getRootNode(), nDepth, aTemplateProvider );
+}
+//-----------------------------------------------------------------------------
+
+ElementTree::ElementTree( rtl::Reference< data::TreeSegment > const& pNewTree,
+ rtl::Reference<Template> aTemplate,
+ TemplateProvider const& aTemplateProvider )
+: Tree()
+, m_aInstanceInfo(aTemplate)
+, m_aOwnData(pNewTree)
+{
+ if (!pNewTree.is())
+ throw Exception("ERROR: Provider can't create Element Instance From Template");
+ m_aElementName = pNewTree->fragment->getName();
+ m_aDataAddress = pNewTree->fragment;
+
+ Tree::build( view::createDirectAccessStrategy(m_aOwnData), m_aOwnData->fragment->nodes, c_TreeDepthAll, aTemplateProvider );
+}
+//-----------------------------------------------------------------------------
+
+ElementTree::~ElementTree()
+{
+}
+//-----------------------------------------------------------------------------
+
+bool ElementTree::isUpdatableSegment(Tree& _rTree)
+{
+ Tree * pTree = &_rTree;
+
+ while (ElementTree * pElement = dynamic_cast< ElementTree * >(pTree))
+ {
+ if (pElement->m_aOwnData.is())
+ {
+ OSL_ENSURE( pElement->getContextTree()==NULL ||
+ pElement->getContextTree()->getViewBehavior() != pElement->getViewBehavior(),
+ "ElementTree with parent in same fragment should not own its data");
+ return true;
+ }
+
+ pTree = pElement->getContextTree();
+
+ if (!pTree)
+ {
+ OSL_ENSURE( false, "ElementTree without own data should have a parent");
+ return false;
+ }
+
+ }
+ OSL_ENSURE( false, "Tree is not part of free-floating segment - cannot support direct update");
+
+ return false;
+}
+//-----------------------------------------------------------------------------
+
+void ElementTree::disposeData()
+{
+ Tree::disposeData();
+ m_aOwnData.clear();
+}
+//-----------------------------------------------------------------------------
+
+Path::Component ElementTree::makeExtendedName(rtl::OUString const& _aSimpleName) const
+{
+ rtl::OUString aTypeName = implGetOriginalName(ROOT);
+
+ OSL_ENSURE(this->isTemplateInstance(), "ElementTree: Cannot discover the type this instantiatiates");
+
+ OSL_ENSURE(! this->isTemplateInstance() || this->getTemplate()->getName() == aTypeName,
+ "ElementTree: Type name does not match template");
+
+ return Path::makeCompositeName(_aSimpleName, aTypeName);
+}
+//-----------------------------------------------------------------------------
+
+// ownership handling
+//-----------------------------------------------------------------------------
+void ElementTree::rebuild(rtl::Reference<view::ViewStrategy> const & _aStrategy, sharable::TreeFragment * newTree)
+{
+ Tree::rebuild(_aStrategy, newTree->getRootNode());
+ m_aDataAddress = newTree;
+ m_aElementName = newTree->getName();
+}
+
+//-----------------------------------------------------------------------------
+/// transfer ownership to the given set
+// -----------------------------------------------------------------------------
+void ElementTree::attachTo(sharable::SetNode * owningSet, rtl::OUString const& aElementName)
+{
+ OSL_ENSURE(m_aOwnData.is(), "ERROR: Cannot add a non-owned node to a subtree");
+
+ if (m_aOwnData.is())
+ {
+ OSL_ENSURE(this->getSimpleRootName() == aElementName,"ElementTree: Attaching with unexpected element name");
+ m_aOwnData->fragment->setName(aElementName);
+
+ Tree* pOwningTree = this->getContextTree();
+ OSL_ENSURE(pOwningTree, "Element Tree Context must be set before attaching data");
+
+ if (isUpdatableSegment(*pOwningTree))
+ {
+ // copy over to the new segment
+ sharable::TreeFragment * aNewElement = data::buildTree(m_aOwnData->fragment);
+
+ owningSet->addElement(aNewElement);
+
+ rtl::Reference<view::ViewStrategy> xNewBehavior = pOwningTree->getViewBehavior();
+
+ this->rebuild(xNewBehavior,aNewElement);
+ }
+ else
+ OSL_ENSURE( false, "Cannot attach directly to new tree - no update access available");
+
+ m_aOwnData.clear();
+ OSL_ASSERT(!m_aOwnData.is());
+ }
+}
+//-----------------------------------------------------------------------------
+
+/// tranfer ownership from the given set
+void ElementTree::detachFrom(sharable::SetNode * owningSet, rtl::OUString const& aElementName)
+{
+ OSL_ENSURE(!m_aOwnData.is(),"ERROR: Cannot detach a already owned node from a subtree");
+ OSL_ENSURE(this->getSimpleRootName() == aElementName,"ElementTree: Detaching with unexpected element name");
+
+ rtl::Reference< view::ViewStrategy > xOldStrategy = this->getViewBehavior();
+ OSL_ENSURE(xOldStrategy.is(), "Element Tree Context must still have the old strategy when detaching data");
+
+ {
+ // make a new segment with a copy of the data
+ rtl::Reference< data::TreeSegment > aNewSegment = data::TreeSegment::create( this->getOriginalTreeAccess() );
+
+ OSL_ENSURE(aNewSegment.is(),"ERROR: Could not create detached copy of elment data");
+
+ this->takeTreeAndRebuild( aNewSegment );
+
+ sharable::TreeFragment * aOldElement = owningSet->removeElement(aElementName );
+ OSL_ENSURE(aOldElement != NULL,"ERROR: Detached node not found in the given subtree");
+
+ data::destroyTree(aOldElement);
+ }
+
+ OSL_ENSURE(m_aOwnData.is(),"ERROR: Could not create own data segment for detached node");
+}
+//-----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+
+/// transfer ownership from the given owner
+void ElementTree::takeTreeBack(rtl::Reference< data::TreeSegment > const & _aDataSegment)
+{
+ OSL_ENSURE(!m_aOwnData.is(), "ERROR: Cannot take over a node - already owning");
+ OSL_ENSURE(_aDataSegment.is(), "ERROR: Cannot take over NULL tree segment");
+
+ m_aOwnData = _aDataSegment;
+ OSL_ENSURE(m_aOwnData.is(), "ERROR: Could not take over data segment");
+
+ m_aDataAddress = m_aOwnData->fragment;
+ m_aElementName = m_aOwnData->fragment->getName();
+}
+//-----------------------------------------------------------------------------
+
+/// transfer ownership from the given owner
+void ElementTree::takeTreeAndRebuild(rtl::Reference< data::TreeSegment > const & _aDataSegment)
+{
+ OSL_ENSURE(!m_aOwnData.is(), "ERROR: Cannot take over a node - already owning");
+ OSL_ENSURE(_aDataSegment.is(), "ERROR: Cannot take over NULL tree segment");
+ this->rebuild(view::createDirectAccessStrategy(_aDataSegment), _aDataSegment->fragment);
+ m_aOwnData = _aDataSegment;
+}
+//-----------------------------------------------------------------------------
+
+/// release ownership
+rtl::Reference< data::TreeSegment > ElementTree::releaseOwnedTree()
+{
+ OSL_ENSURE(m_aOwnData.is(), "ERROR: Cannot release and rename a non-owned node");
+ rtl::Reference< data::TreeSegment > aTree(m_aOwnData);
+ m_aOwnData.clear();
+ aTree->fragment->setName(m_aElementName);
+ return aTree;
+}
+//-----------------------------------------------------------------------------
+
+// context handling
+//-----------------------------------------------------------------------------
+
+/// renames the tree's root without concern for context consistency !
+void ElementTree::renameTree(rtl::OUString const& aNewName)
+{
+ m_aElementName = aNewName;
+}
+//-----------------------------------------------------------------------------
+
+void ElementTree::moveTree(Tree* pParentTree, unsigned int nParentNode)
+{
+ Tree::setContext(pParentTree,nParentNode);
+}
+//-----------------------------------------------------------------------------
+
+void ElementTree::detachTree()
+{
+ Tree::clearContext();
+}
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+ } // namespace configuration
+} // namespace configmgr
+