1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: treeimpl.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
34 #include "anynoderef.hxx"
35 #include "builddata.hxx"
36 #include "configset.hxx"
39 #include "roottreeimpl.hxx"
40 #include "nodeimpl.hxx"
41 #include "nodechange.hxx"
42 #include "nodechangeimpl.hxx"
43 #include "noderef.hxx"
44 #include "template.hxx"
45 #include "nodevisitor.hxx"
46 #include "valueref.hxx"
47 #include "valuenode.hxx"
49 #include "valuenodeimpl.hxx"
50 #include "setnodeimpl.hxx"
51 #include "groupnodeimpl.hxx"
52 #include "viewaccess.hxx"
53 #include "viewfactory.hxx"
54 #include "nodefactory.hxx"
55 #include <osl/diagnose.h>
59 //-----------------------------------------------------------------------------
60 namespace configuration
62 //-----------------------------------------------------------------------------
63 // class TreeImplBuilder - friend of Tree
64 //-----------------------------------------------------------------------------
66 /** is a visitor-style algorithm to construct a <type>Tree::NodeList</type>
67 representing a configuration hierarchy
69 class TreeImplBuilder
: public data::NodeVisitor
72 /** constructs a TreeImplBuilder to append onto <var>rList</var>
73 the products of <var>rFactory</var> up to depth <var>nDepth</var>
76 TemplateProvider
const& aTemplateProvider
,
77 rtl::Reference
<view::ViewStrategy
> const& _xStrategy
,
80 : m_xStrategy(_xStrategy
)
81 , m_aTemplateProvider(aTemplateProvider
)
82 , m_rFactory(_xStrategy
->getNodeFactory())
85 , m_nDepthLeft(rTree
.m_nDepth
)
87 OSL_ASSERT(m_rTree
.m_aNodes
.empty());
88 OSL_DEBUG_ONLY(m_bMemberCheck
= false);
89 m_rTree
.m_xStrategy
= _xStrategy
;
93 using NodeVisitor::handle
;
95 virtual bool handle(sharable::ValueNode
* node
);
97 virtual bool handle(sharable::GroupNode
* node
);
99 virtual bool handle(sharable::SetNode
* node
);
101 /// add a Node for group node <var>_aGroup</var> to the list
102 void addGroup(sharable::GroupNode
* group
);
103 /// add a Node for set node <var>_aSet</var> to the list
104 void addSet(sharable::SetNode
* set
);
105 /// add a Node for value node <var>rValue</var> to the list
106 void addValueElement(sharable::ValueNode
* value
);
107 /// add a Member for value node <var>rValue</var> to the list
108 void addValueMember(sharable::ValueNode
* value
);
110 rtl::Reference
<view::ViewStrategy
> m_xStrategy
;
111 TemplateProvider m_aTemplateProvider
;
112 view::NodeFactory
& m_rFactory
;
114 unsigned int m_nParent
;
115 unsigned int m_nDepthLeft
;
116 #if OSL_DEBUG_LEVEL > 0
120 //-----------------------------------------------------------------------------
122 bool TreeImplBuilder::handle(sharable::ValueNode
* node
)
125 addValueElement(node
); // if it is the root it is a value set element
127 addValueMember(node
); // if it is not the root it is a group member
131 //-----------------------------------------------------------------------------
133 bool TreeImplBuilder::handle(sharable::GroupNode
* node
)
138 //-----------------------------------------------------------------------------
140 bool TreeImplBuilder::handle(sharable::SetNode
* node
)
145 //-----------------------------------------------------------------------------
147 void TreeImplBuilder::addValueElement(sharable::ValueNode
* value
)
149 rtl::Reference
<NodeImpl
> aValueNode( m_rFactory
.makeValueNode(value
) );
150 OSL_ENSURE( aValueNode
.is(), "could not make value node wrapper" );
152 OSL_ENSURE( m_nParent
== 0, "Adding value element that is not root of its fragment" );
153 // TODO:!isValid() => maybe substitute a SimpleValueNodeImpl if possible
154 if( aValueNode
.is() )
156 m_rTree
.m_aNodes
.push_back( NodeData(aValueNode
, value
->info
.getName(), m_nParent
) );
159 //-----------------------------------------------------------------------------
161 void TreeImplBuilder::addValueMember(sharable::ValueNode
*)
164 OSL_DEBUG_ONLY(m_bMemberCheck
= true);
166 //-----------------------------------------------------------------------------
168 void TreeImplBuilder::addGroup(sharable::GroupNode
* group
)
170 rtl::Reference
<NodeImpl
> aGroupNode( m_rFactory
.makeGroupNode(group
) );
171 OSL_ENSURE( aGroupNode
.is(), "could not make group node wrapper" );
173 // TODO:!isValid() => maybe substitute a SimpleValueNodeImpl if possible
174 if( aGroupNode
.is() )
176 m_rTree
.m_aNodes
.push_back( NodeData(aGroupNode
,group
->info
.getName(),m_nParent
) );
178 // now fill in group members
179 if (m_nDepthLeft
> 0)
181 unsigned int nSaveParent
= m_nParent
;
182 decDepth(m_nDepthLeft
);
184 m_nParent
= m_rTree
.m_aNodes
.size() + Tree::ROOT
- 1;
186 #if OSL_DEBUG_LEVEL > 0
187 bool bSaveMemberCheck
= m_bMemberCheck
;
188 m_bMemberCheck
= false;
192 this->visitChildren(group
);
194 OSL_ENSURE(m_nParent
< m_rTree
.m_aNodes
.size() || m_bMemberCheck
,
195 "WARNING: Configuration: Group within requested depth has no members");
197 OSL_DEBUG_ONLY(m_bMemberCheck
= bSaveMemberCheck
);
199 incDepth(m_nDepthLeft
);
200 m_nParent
= nSaveParent
;
204 //-----------------------------------------------------------------------------
206 void TreeImplBuilder::addSet(sharable::SetNode
* set
)
208 rtl::Reference
<Template
> aTemplate
= makeSetElementTemplate(set
, m_aTemplateProvider
);
209 OSL_ASSERT(aTemplate
.is());
210 OSL_ENSURE(aTemplate
->isInstanceTypeKnown(),"ERROR: Cannor create set instance without knowing the instance type");
212 rtl::Reference
<NodeImpl
> aSetNode( m_rFactory
.makeSetNode(set
, aTemplate
.get()) );
213 OSL_ENSURE( aSetNode
.is(), "could not make set node wrapper" );
215 // TODO:!isValid() => maybe substitute a SimpleValueNodeImpl if possible
218 m_rTree
.m_aNodes
.push_back( NodeData(aSetNode
, set
->info
.getName(), m_nParent
) );
220 // this also relies on one based offsets
221 unsigned int nNodeAdded
= m_rTree
.m_aNodes
.size() + Tree::ROOT
- 1;
223 OSL_ASSERT(&m_rTree
.m_aNodes
.back().nodeImpl() == aSetNode
.get());
224 static_cast<SetNodeImpl
&>(*aSetNode
).initElements(m_aTemplateProvider
, m_rTree
, nNodeAdded
, m_nDepthLeft
);
229 class FindNonDefaultElement
: public SetNodeVisitor
{
231 static bool hasNonDefaultElement(
232 view::ViewTreeAccess
const & view
, view::SetNode
const & set
)
234 FindNonDefaultElement visitor
;
235 return view
.dispatchToElements(set
, visitor
) == DONE
;
239 virtual Result
visit(SetEntry
const & entry
) {
240 OSL_ASSERT(entry
.isValid());
241 rtl::Reference
< Tree
> tree(entry
.tree());
242 OSL_ASSERT(tree
.is());
243 node::Attributes
atts(tree
->getAttributes(tree
->getRootNode()));
244 // A set element is considered default iff it is not replaced/added:
245 bool dflt
= !atts
.isReplacedForUser();
246 return dflt
? CONTINUE
: DONE
;
250 class SetVisitorAdapter
: public SetNodeVisitor
{
252 explicit SetVisitorAdapter(NodeVisitor
& visitor
): m_visitor(visitor
) {}
255 virtual Result
visit(SetEntry
const & entry
) {
256 OSL_ASSERT(entry
.isValid());
257 rtl::Reference
< Tree
> tree(entry
.tree());
260 Result(NodeVisitor::DONE
) == SetNodeVisitor::DONE
&&
261 Result(NodeVisitor::CONTINUE
) == SetNodeVisitor::CONTINUE
);
262 return Result(tree
->visit(tree
->getRootNode(), m_visitor
));
269 NodeVisitor
& m_visitor
;
272 class GroupVisitorAdapter
: public GroupMemberVisitor
{
275 rtl::Reference
< Tree
> const & parentTree
,
276 NodeRef
const & parentNode
, NodeVisitor
& visitor
):
277 m_parentTree(parentTree
), m_parentPos(parentNode
.getOffset()),
281 !isEmpty(parentTree
.get()) && parentNode
.isValid() &&
282 parentTree
->isValidNode(parentNode
.getOffset()));
286 virtual Result
visit(ValueMemberNode
const & value
) {
289 Result(NodeVisitor::DONE
) == GroupMemberVisitor::DONE
&&
290 Result(NodeVisitor::CONTINUE
) == GroupMemberVisitor::CONTINUE
);
293 ValueRef(value
.getNodeName(), m_parentPos
), m_visitor
));
297 rtl::Reference
< Tree
> m_parentTree
;
298 unsigned int m_parentPos
;
299 NodeVisitor
& m_visitor
;
303 //-----------------------------------------------------------------------------
305 //-----------------------------------------------------------------------------
307 NodeData::NodeData(rtl::Reference
<NodeImpl
> const& aSpecificNode
, rtl::OUString
const& aName
, unsigned int nParent
)
308 : m_pSpecificNode(aSpecificNode
)
314 //-----------------------------------------------------------------------------
316 void NodeData::rebuild(rtl::Reference
<view::ViewStrategy
> const & _xNewStrategy
, sharable::Node
* newData
)
318 rtl::Reference
<NodeImpl
> aNewImpl
;
319 if (this->isSetNode())
321 sharable::SetNode
* newSet
= newData
== 0 ? 0 : newData
->setData();
322 aNewImpl
= _xNewStrategy
->getNodeFactory().makeSetNode(newSet
, 0);
324 SetNodeImpl
& rOldSetData
= this->setImpl();
325 SetNodeImpl
& rNewSetData
= static_cast<SetNodeImpl
&>(*aNewImpl
);
327 rNewSetData
.rebuildFrom(rOldSetData
, newSet
);
329 else if (this->isGroupNode())
330 aNewImpl
= _xNewStrategy
->getNodeFactory().makeGroupNode(newData
== 0 ? 0 : newData
->groupData());
332 else if (this->isValueElementNode())
333 aNewImpl
= _xNewStrategy
->getNodeFactory().makeValueNode(newData
== 0 ? 0 : newData
->valueData());
335 m_pSpecificNode
= aNewImpl
;
338 //-----------------------------------------------------------------------------
340 bool NodeData::isSetNode() const
342 sharable::Node
* node
= getOriginalNodeAccess();
343 return node
!= 0 && node
->isSet();
345 //-----------------------------------------------------------------------------
347 bool NodeData::isValueElementNode() const
349 sharable::Node
* node
= getOriginalNodeAccess();
350 return node
!= 0 && node
->isValue();
352 //-----------------------------------------------------------------------------
354 bool NodeData::isGroupNode() const
356 sharable::Node
* node
= getOriginalNodeAccess();
357 return node
!= 0 && node
->isGroup();
359 //-----------------------------------------------------------------------------
361 SetNodeImpl
& NodeData::implGetSetImpl() const
363 OSL_ASSERT(m_pSpecificNode
!= 0);
364 OSL_ASSERT(isSetNode());
367 throw Exception( "INTERNAL ERROR: Node is not a set node. Cast failing." );
369 return static_cast<SetNodeImpl
&>(*m_pSpecificNode
);
371 //---------------------------------------------------------------------
373 GroupNodeImpl
& NodeData::implGetGroupImpl() const
375 OSL_ASSERT(m_pSpecificNode
!= 0);
376 OSL_ASSERT(isGroupNode());
379 throw Exception( "INTERNAL ERROR: Node is not a group node. Cast failing." );
381 return static_cast<GroupNodeImpl
&>(*m_pSpecificNode
);
383 //---------------------------------------------------------------------
385 ValueElementNodeImpl
& NodeData::implGetValueImpl() const
387 OSL_ASSERT(m_pSpecificNode
!= 0);
388 OSL_ASSERT(isValueElementNode());
390 if (!isValueElementNode())
391 throw Exception( "INTERNAL ERROR: Node is not a value node. Cast failing." );
393 return static_cast<ValueElementNodeImpl
&>(*m_pSpecificNode
);
396 sharable::Node
* NodeData::getOriginalNodeAccess() const
398 return m_pSpecificNode
->getOriginalNodeAccess();
401 NodeImpl
& NodeData::implGetNodeImpl() const
403 OSL_ASSERT(m_pSpecificNode
!= 0);
404 return *m_pSpecificNode
;
407 //-----------------------------------------------------------------------------
409 //-----------------------------------------------------------------------------
411 //-----------------------------------------------------------------------------
413 /// creates a Tree for a detached, virgin instance of <var>aTemplate</var>
421 //-----------------------------------------------------------------------------
423 Tree::Tree( Tree
& rParentTree
, unsigned int nParentNode
)
425 , m_pParentTree(&rParentTree
)
426 , m_nParentNode(nParentNode
)
430 //-----------------------------------------------------------------------------
435 //-----------------------------------------------------------------------------
437 void Tree::disposeData()
442 bool Tree::isRootNode(NodeRef
const & node
) const {
444 nodeCount() != 0 && (!node
.isValid() || isValidNode(node
.getOffset())));
445 return node
.isValid() && node
.getOffset() == ROOT
;
448 NodeRef
Tree::getRootNode() const {
449 OSL_ASSERT(nodeCount() != 0);
450 return NodeRef(ROOT
, m_nDepth
);
453 NodeRef
Tree::getContextNodeRef() const {
454 OSL_ASSERT(nodeCount() != 0 && (m_pParentTree
== 0 || m_nParentNode
!= 0));
455 return m_pParentTree
== 0
456 ? NodeRef() : m_pParentTree
->getNode(m_nParentNode
);
459 bool Tree::isValidValueNode(ValueRef
const & value
) {
460 OSL_ASSERT(nodeCount() != 0);
461 if (!(value
.isValid() &&
462 value
.checkValidState() &&
463 isValidNode(value
.m_nParentPos
) &&
464 view::ViewTreeAccess(this).isGroupNodeAt(value
.m_nParentPos
) &&
465 getMemberNode(value
).isValid()))
469 OSL_ASSERT(value
.m_sNodeName
.getLength() != 0); // old value handling?
473 #if OSL_DEBUG_LEVEL > 0
474 bool Tree::isValidAnyNode(AnyNodeRef
const & node
) {
475 OSL_ASSERT(nodeCount() != 0);
476 return node
.isValid() && isValidNode(node
.m_nUsedPos
) &&
478 (view::ViewTreeAccess(this).isGroupNodeAt(node
.m_nUsedPos
) &&
479 getMemberNode(node
.toValue()).isValid()));
483 bool Tree::hasElements(NodeRef
const & node
) {
485 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
486 if (node
.getDepth() == 0) {
488 "configuration: Querying node beyond available depth" );
490 view::ViewTreeAccess
v(this);
491 return v
.isSetNode(node
) && !v
.isEmpty(v
.toSetNode(node
));
494 bool Tree::hasElement(NodeRef
const & node
, rtl::OUString
const & name
) {
496 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
497 if (node
.getDepth() == 0) {
499 "configuration: Querying node beyond available depth");
501 view::ViewTreeAccess
v(this);
502 return v
.isSetNode(node
) &&
503 v
.findElement(v
.toSetNode(node
), name
).isValid();
506 bool Tree::hasElement(NodeRef
const & node
, Path::Component
const & name
) {
508 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
509 if (node
.getDepth() == 0) {
511 "configuration: Querying node beyond available depth");
513 view::ViewTreeAccess
v(this);
514 if (v
.isSetNode(node
)) {
515 SetEntry
e(v
.findElement(v
.toSetNode(node
), name
.getName()));
516 // Check if types match:
517 return e
.isValid() &&
518 Path::matches(e
.tree()->getExtendedRootName(), name
);
524 rtl::Reference
< ElementTree
> Tree::getElement(NodeRef
const & node
, rtl::OUString
const & name
) {
526 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
527 if (node
.getDepth() == 0) {
529 "configuration: Querying node beyond available depth");
531 view::ViewTreeAccess
v(this);
532 if (v
.isSetNode(node
)) {
533 SetEntry
e(v
.findElement(v
.toSetNode(node
), name
));
534 return rtl::Reference
< ElementTree
>(e
.tree());
536 return rtl::Reference
< ElementTree
>();
540 rtl::Reference
< ElementTree
> Tree::getAvailableElement(
541 NodeRef
const & node
, rtl::OUString
const & name
)
544 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
545 view::ViewTreeAccess
v(this);
546 if (v
.isSetNode(node
)) {
547 SetEntry
e(v
.findAvailableElement(v
.toSetNode(node
), name
));
548 return rtl::Reference
< ElementTree
>(e
.tree());
550 return rtl::Reference
< ElementTree
>();
554 bool Tree::hasChildren(NodeRef
const & node
) {
556 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
557 if (node
.getDepth() == 0) {
559 "configuration: Querying node beyond available depth");
561 view::ViewTreeAccess
v(this);
562 if (v
.isGroupNode(node
)) {
563 view::GroupNode
g(v
.toGroupNode(node
));
564 return v
.hasValue(g
) || g
.getFirstChild().is();
570 bool Tree::hasChildValue(NodeRef
const & node
, rtl::OUString
const & name
) {
572 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
573 if (node
.getDepth() == 0) {
575 "configuration: Querying node beyond available depth");
577 view::ViewTreeAccess
v(this);
578 return v
.isGroupNode(node
) && v
.hasValue(v
.toGroupNode(node
), name
);
581 bool Tree::hasChildNode(NodeRef
const & node
, rtl::OUString
const & name
) {
583 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
584 if (node
.getDepth() == 0) {
586 "configuration: Querying node beyond available depth");
588 view::ViewTreeAccess
v(this);
589 return v
.isGroupNode(node
) && v
.toGroupNode(node
).findChild(name
).is();
592 bool Tree::hasChild(NodeRef
const & node
, rtl::OUString
const & name
) {
594 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
595 if (node
.getDepth() == 0) {
597 "configuration: Querying node beyond available depth");
599 view::ViewTreeAccess
v(this);
600 if (v
.isGroupNode(node
)) {
601 view::GroupNode
g(v
.toGroupNode(node
));
602 return v
.hasValue(g
, name
) || g
.findChild(name
).is();
608 ValueRef
Tree::getChildValue(NodeRef
const & node
, rtl::OUString
const & name
) {
610 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
611 if (node
.getDepth() == 0) {
613 "configuration: Querying node beyond available depth");
615 view::ViewTreeAccess
v(this);
616 return v
.isGroupNode(node
) && v
.hasValue(v
.toGroupNode(node
), name
)
617 ? ValueRef(name
, node
.getOffset()) : ValueRef();
620 NodeRef
Tree::getChildNode(NodeRef
const & node
, rtl::OUString
const & name
)
623 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
624 if (node
.getDepth() == 0) {
626 "configuration: Querying node beyond available depth");
628 view::ViewTreeAccess
v(this);
631 ? v
.toGroupNode(node
).findChild(name
).get_offset() : 0),
632 childDepth(node
.getDepth()));
635 AnyNodeRef
Tree::getAnyChild(NodeRef
const & node
, rtl::OUString
const & name
) {
637 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
638 if (node
.getDepth() == 0) {
640 "configuration: Querying node beyond available depth");
642 view::ViewTreeAccess
v(this);
644 if (v
.isGroupNode(node
)) {
645 if (v
.hasValue(v
.toGroupNode(node
), name
)) {
646 return AnyNodeRef(name
, node
.getOffset());
648 n
= v
.toGroupNode(node
).findChild(name
).get_offset();
650 return AnyNodeRef(n
, childDepth(node
.getDepth()));
653 node::Attributes
Tree::getAttributes(NodeRef
const & node
) {
655 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
656 return view::ViewTreeAccess(this).getAttributes(node
);
659 node::Attributes
Tree::getAttributes(AnyNodeRef
const & node
) {
660 OSL_ASSERT(nodeCount() != 0 && isValidAnyNode(node
));
662 return view::ViewTreeAccess(this).getAttributes(node
.toNode());
664 return getMemberNode(node
.toValue()).getAttributes();
668 node::Attributes
Tree::getAttributes(ValueRef
const & value
) {
669 OSL_ASSERT(nodeCount() != 0 && isValidValueNode(value
));
670 return getMemberNode(value
).getAttributes();
673 com::sun::star::uno::Type
Tree::getUnoType(ValueRef
const & value
) {
674 OSL_ASSERT(nodeCount() != 0 && isValidValueNode(value
));
675 return getMemberNode(value
).getValueType();
678 NodeRef
Tree::getParent(NodeRef
const & node
) {
680 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
681 view::ViewTreeAccess
v(this);
682 OSL_ASSERT(!v
.makeNode(getRootNode()).getParent().is());
683 view::Node
p(v
.makeNode(node
).getParent());
684 OSL_ASSERT(isValidNode(p
.get_offset()));
685 return NodeRef(p
.get_offset(), parentDepth(node
.getDepth()));
688 NodeRef
Tree::getParent(ValueRef
const & value
) {
689 OSL_ASSERT(nodeCount() != 0 && isValidValueNode(value
));
690 unsigned int n
= value
.m_nParentPos
;
691 OSL_ASSERT(n
== 0 || value
.m_sNodeName
.getLength() != 0);
695 AbsolutePath
Tree::getAbsolutePath(NodeRef
const & node
) {
697 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
699 prependLocalPathTo(node
.getOffset(), r
);
700 r
.prepend(getRootPath().rep());
701 return AbsolutePath(r
);
704 com::sun::star::uno::Any
Tree::getNodeValue(ValueRef
const & value
) {
705 OSL_ASSERT(isValidValueNode(value
));
706 return getMemberNode(value
).getValue();
709 bool Tree::hasNodeDefault(ValueRef
const & value
) {
710 OSL_ASSERT(nodeCount() != 0 && isValidValueNode(value
));
711 return getMemberNode(value
).canGetDefaultValue();
714 bool Tree::isNodeDefault(ValueRef
const & value
) {
715 OSL_ASSERT(nodeCount() != 0 && isValidValueNode(value
));
716 return hasNodeDefault(value
) && getMemberNode(value
).isDefault();
719 bool Tree::hasNodeDefault(NodeRef
const & node
) {
721 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
722 // Not a set, then it has no default:
723 return view::ViewTreeAccess(this).isSetNode(node
);
726 bool Tree::isNodeDefault(NodeRef
const & node
) {
728 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
729 if (!hasNodeDefault(node
)) {
732 view::ViewTreeAccess
v(this);
733 OSL_ASSERT(v
.isSetNode(node
)); // not a set, then it has no default
734 // A set is default if all its elements are default:
735 return !FindNonDefaultElement::hasNonDefaultElement(v
, v
.toSetNode(node
));
738 bool Tree::hasNodeDefault(AnyNodeRef
const & node
) {
739 OSL_ASSERT(nodeCount() != 0 && isValidAnyNode(node
));
741 ? hasNodeDefault(node
.toNode()) : hasNodeDefault(node
.toValue());
744 bool Tree::isNodeDefault(AnyNodeRef
const & node
) {
745 OSL_ASSERT(nodeCount() != 0 && isValidAnyNode(node
));
747 ? isNodeDefault(node
.toNode()) : isNodeDefault(node
.toValue());
750 bool Tree::areValueDefaultsAvailable(NodeRef
const & node
) {
752 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
753 view::ViewTreeAccess
v(this);
754 OSL_ASSERT(v
.isGroupNode(node
));
755 return v
.isGroupNode(node
) &&
756 v
.areValueDefaultsAvailable(v
.toGroupNode(node
));
759 com::sun::star::uno::Any
Tree::getNodeDefaultValue(ValueRef
const & value
) {
760 OSL_ASSERT(nodeCount() != 0 && isValidValueNode(value
));
761 ValueMemberNode
m(getMemberNode(value
));
762 return m
.canGetDefaultValue() ?
763 m
.getDefaultValue() : com::sun::star::uno::Any();
766 bool Tree::hasChanges() {
767 return view::ViewTreeAccess(this).hasChanges();
770 bool Tree::collectChanges(NodeChanges
& changes
) {
771 OSL_ASSERT(nodeCount() != 0);
772 view::ViewTreeAccess
v(this);
773 if (v
.hasChanges()) {
774 v
.collectChanges(changes
);
781 void Tree::integrate(NodeChange
& change
, NodeRef
const & node
, bool local
)
784 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
785 if (change
.test().isChange()) {
788 view::ViewTreeAccess(this).markChanged(node
);
790 rtl::Reference
< Tree
> at(change
.getAffectedTree());
791 NodeRef
an(change
.getAffectedNode());
793 !isEmpty(at
.get()) && an
.isValid() &&
794 at
->isValidNode(an
.getOffset()));
795 view::ViewTreeAccess(at
.get()).markChanged(an
);
796 OSL_ASSERT(view::ViewTreeAccess(this).hasChanges());
801 void Tree::integrate(NodeChanges
& changes
, NodeRef
const & node
, bool local
)
803 for (std::vector
< NodeChange
>::iterator
it(changes
.begin());
804 it
!= changes
.end(); ++it
)
806 integrate(*it
, node
, local
);
810 NodeVisitor::Result
Tree::dispatchToChildren(
811 NodeRef
const & node
, NodeVisitor
& visitor
)
814 nodeCount() != 0 && node
.isValid() && isValidNode(node
.getOffset()));
815 if (node
.getDepth() == 0) {
817 "configuration: Querying node beyond available depth");
819 view::ViewTreeAccess
v(this);
820 if (v
.isGroupNode(node
)) {
821 view::GroupNode
const p(v
.toGroupNode(node
));
823 (NodeVisitor::Result(GroupMemberVisitor::DONE
) ==
824 NodeVisitor::DONE
) &&
825 (NodeVisitor::Result(GroupMemberVisitor::CONTINUE
) ==
826 NodeVisitor::CONTINUE
));
827 GroupVisitorAdapter
adapter(this, node
, visitor
);
828 NodeVisitor::Result ret
= NodeVisitor::Result(
829 v
.dispatchToValues(p
, adapter
));
830 unsigned int n
= childDepth(node
.getDepth());
831 for (view::Node
c(p
.getFirstChild());
832 c
.is() && ret
!= NodeVisitor::DONE
; c
= p
.getNextChild(c
))
834 ret
= visit(NodeRef(c
.get_offset(), n
), visitor
);
837 } else if (v
.isSetNode(node
)) {
839 NodeVisitor::Result(SetNodeVisitor::DONE
) == NodeVisitor::DONE
&&
840 (NodeVisitor::Result(SetNodeVisitor::CONTINUE
) ==
841 NodeVisitor::CONTINUE
));
842 SetVisitorAdapter
adapter(visitor
);
843 return NodeVisitor::Result(
844 v
.dispatchToElements(v
.toSetNode(node
), adapter
));
846 OSL_TRACE("configuration: Trying to iterate a value node");
847 return NodeVisitor::CONTINUE
;
851 NodeRef
Tree::getNode(unsigned int offset
) const {
855 OSL_ASSERT(isValidNode(offset
));
857 offset
, remainingDepth(getAvailableDepth(), depthTo(offset
)));
861 rtl::Reference
< Template
> Tree::extractElementInfo(NodeRef
const & node
) {
862 OSL_ASSERT(node
.isValid() && isValidNode(node
.getOffset()));
863 view::ViewTreeAccess
v(this);
864 OSL_ASSERT(v
.isSetNode(node
));
865 return v
.getElementTemplate(v
.toSetNode(node
));
868 //-----------------------------------------------------------------------------
869 void Tree::rebuild(rtl::Reference
<view::ViewStrategy
> const & _xNewStrategy
, sharable::Node
* newData
)
871 m_xStrategy
= _xNewStrategy
;
872 this->implRebuild(ROOT
, newData
);
875 //-----------------------------------------------------------------------------
876 void Tree::implRebuild(unsigned int nNode
, sharable::Node
* newData
)
878 NodeData
* pNode
= nodeData(nNode
);
879 if (pNode
->isGroupNode())
881 // first rebuild the children
882 OSL_ASSERT(newData
!= 0 && newData
->isGroup());
883 sharable::GroupNode
* newGroup
= &newData
->group
;
885 for (unsigned int nChild
= firstChild_(nNode
); isValidNode(nChild
); nChild
= findNextChild_(nNode
,nChild
))
887 sharable::Node
* childAccess
= newGroup
->getChild(implGetOriginalName(nChild
));
888 OSL_ASSERT(childAccess
!= 0);
889 implRebuild(nChild
, childAccess
);
893 pNode
->rebuild(m_xStrategy
, newData
);
896 //-----------------------------------------------------------------------------
898 void ElementTree::doFinishRootPath(Path::Rep
& rPath
) const
900 rPath
.prepend( doGetRootName() );
901 rPath
.prepend( AbsolutePath::detachedRoot().rep() );
903 //-----------------------------------------------------------------------------
905 void RootTree::doFinishRootPath(Path::Rep
& rPath
) const
907 rPath
.prepend( m_aRootPath
.rep() );
910 //-----------------------------------------------------------------------------
912 void Tree::implPrependRootPath(Path::Rep
& rPath
) const
916 rPath
.prepend( doGetRootName() );
917 OSL_ASSERT(m_nParentNode
);
918 m_pParentTree
->prependLocalPathTo(m_nParentNode
,rPath
);
919 m_pParentTree
->implPrependRootPath(rPath
);
923 doFinishRootPath( rPath
);
926 //-----------------------------------------------------------------------------
928 AbsolutePath
Tree::getRootPath() const
931 implPrependRootPath(aPath
);
932 return AbsolutePath(aPath
);
934 //-----------------------------------------------------------------------------
935 void Tree::build(rtl::Reference
<view::ViewStrategy
> const& _xStrategy
, sharable::Node
* rootNode
, unsigned int nDepth
, TemplateProvider
const& aTemplateProvider
)
937 OSL_ASSERT(m_aNodes
.empty());
939 TreeImplBuilder
a(aTemplateProvider
, _xStrategy
,*this);
940 a
.visitNode(rootNode
);
942 //-----------------------------------------------------------------------------
944 rtl::Reference
< view::ViewStrategy
> Tree::getViewBehavior() const
950 //-----------------------------------------------------------------------------
952 void Tree::setContext(Tree
* pParentTree
, unsigned int nParentNode
)
954 OSL_ENSURE(pParentTree
,"ERROR: Moving tree to nowhere");
958 OSL_ENSURE( pParentTree
->isValidNode(nParentNode
),"ERROR: Moving tree to invalid node");
959 if (!pParentTree
->isValidNode(nParentNode
))
960 throw Exception("INTERNAL ERROR: Moving tree to invalid parent node");
962 // OSL_ENSURE( pParentTree->isSetNodeAt(nParentNode),"WARNING: Moving tree to node that is not a set");
966 OSL_ENSURE( nParentNode
== 0,"WARNING: Moving tree to node without a tree");
970 m_pParentTree
= pParentTree
;
971 m_nParentNode
= nParentNode
;
973 //-----------------------------------------------------------------------------
975 void Tree::clearContext()
980 //-----------------------------------------------------------------------------
982 //-----------------------------------------------------------------------------
983 // Node Collection navigation
984 //-----------------------------------------------------------------------------
986 unsigned int Tree::parent_(unsigned int nNode
) const
988 OSL_ASSERT(isValidNode(nNode
));
989 return nodeData(nNode
)->getParent();
991 //-----------------------------------------------------------------------------
992 inline // is protected and should be used only here
993 rtl::OUString
Tree::implGetOriginalName(unsigned int nNode
) const
995 OSL_ASSERT(isValidNode(nNode
));
997 return nodeData(nNode
)->getName();
999 //-----------------------------------------------------------------------------
1001 Path::Component
ElementTree::doGetRootName() const
1003 return makeExtendedName( m_aElementName
);
1006 //-----------------------------------------------------------------------------
1008 rtl::OUString
ElementTree::getSimpleRootName() const
1010 // Tree::getSimpleRootName tends to parse &
1011 // then split the same name, burning CPU L&R
1012 return m_aElementName
;
1015 //-----------------------------------------------------------------------------
1017 Path::Component
RootTree::doGetRootName() const
1019 return m_aRootPath
.getLocalName();
1021 //-----------------------------------------------------------------------------
1024 rtl::OUString
Tree::getSimpleNodeName(unsigned int nNode
) const
1026 if (nNode
== ROOT
) return getSimpleRootName();
1028 return implGetOriginalName(nNode
);
1030 //-----------------------------------------------------------------------------
1032 rtl::OUString
Tree::getSimpleRootName() const
1034 return doGetRootName().getName();
1037 //-----------------------------------------------------------------------------
1039 Path::Component
Tree::getExtendedRootName() const
1041 return doGetRootName();
1043 //-----------------------------------------------------------------------------
1045 unsigned int Tree::depthTo(unsigned int nNode
) const
1047 OSL_ASSERT(isValidNode(nNode
));
1049 unsigned int nDepth
= 0;
1050 while( 0 != (nNode
=parent_(nNode
)) )
1057 //-----------------------------------------------------------------------------
1059 void Tree::prependLocalPathTo(unsigned int nNode
, Path::Rep
& rNames
)
1061 OSL_ASSERT(isValidNode(nNode
));
1063 for (; nNode
!= ROOT
; nNode
= parent_(nNode
) )
1065 OSL_ENSURE( isValidNode(nNode
), "ERROR: Configuration: node has invalid parent");
1066 rNames
.prepend( Path::wrapSimpleName( implGetOriginalName(nNode
) ) );
1069 OSL_ASSERT(nNode
== ROOT
);
1071 //-----------------------------------------------------------------------------
1073 // Node iteration and access
1074 unsigned int Tree::firstChild_ (unsigned int nParent
) const
1076 return findNextChild_(nParent
,nParent
);
1078 //-----------------------------------------------------------------------------
1080 unsigned int Tree::findNextChild_(unsigned int nParent
, unsigned int nStartAfter
) const
1082 OSL_ASSERT(isValidNode(nParent
));
1083 OSL_ASSERT(nStartAfter
== 0 || isValidNode(nStartAfter
));
1085 unsigned int nPos
= nStartAfter
? nStartAfter
: ROOT
- 1;
1086 unsigned int const nAfterLast
= nodeCount() + ROOT
;
1087 while (++nPos
< nAfterLast
)
1089 if(parent_(nPos
) == nParent
) return nPos
;
1093 //-----------------------------------------------------------------------------
1095 unsigned int Tree::findChild_(unsigned int nParent
, rtl::OUString
const& aName
) const
1097 OSL_ASSERT(isValidNode(nParent
));
1099 unsigned int nPos
= nParent
;
1100 unsigned int const nAfterLast
= nodeCount() + ROOT
;
1101 while (++nPos
< nAfterLast
)
1103 if(parent_(nPos
) == nParent
&& implGetOriginalName(nPos
) == aName
)
1109 ValueMemberNode
Tree::getMemberNode(ValueRef
const & value
) {
1110 OSL_ASSERT(nodeCount() != 0);
1111 view::ViewTreeAccess
v(this);
1112 return v
.getValue(v
.getGroupNodeAt(value
.m_nParentPos
), value
.m_sNodeName
);
1115 //-----------------------------------------------------------------------------
1117 //-----------------------------------------------------------------------------
1119 RootTree::RootTree( rtl::Reference
<view::ViewStrategy
> const& _xStrategy
,
1120 AbsolutePath
const& aRootPath
,
1121 sharable::Node
* cacheNode
, unsigned int nDepth
,
1122 TemplateProvider
const& aTemplateProvider
)
1124 , m_aRootPath(aRootPath
)
1126 // OSL_ENSURE( aRootPath.getLocalName().getName() == cacheNode->getName(),
1127 // "Constructing root node: Path does not match node name");
1129 Tree::build(_xStrategy
,cacheNode
,nDepth
,aTemplateProvider
);
1132 bool isEmpty(Tree
* tree
)
1134 return tree
== 0 || tree
->nodeCount() == 0;
1137 //-----------------------------------------------------------------------------
1138 // class ElementTree
1139 //-----------------------------------------------------------------------------
1141 ElementTree::ElementTree( rtl::Reference
<view::ViewStrategy
> const& _xStrategy
,
1142 sharable::TreeFragment
* cacheTree
, unsigned int nDepth
,
1143 rtl::Reference
<Template
> aTemplateInfo
,
1144 TemplateProvider
const& aTemplateProvider
)
1146 , m_aInstanceInfo(aTemplateInfo
)
1147 , m_aElementName(cacheTree
->getName())
1148 , m_aDataAddress(cacheTree
)
1151 Tree::build( _xStrategy
, cacheTree
->getRootNode(), nDepth
, aTemplateProvider
);
1153 //-----------------------------------------------------------------------------
1155 ElementTree::ElementTree( rtl::Reference
<view::ViewStrategy
> const& _xStrategy
,
1156 Tree
& rParentTree
, unsigned int nParentNode
,
1157 sharable::TreeFragment
* cacheTree
, unsigned int nDepth
,
1158 rtl::Reference
<Template
> aTemplateInfo
,
1159 TemplateProvider
const& aTemplateProvider
)
1160 : Tree( rParentTree
, nParentNode
)
1161 , m_aInstanceInfo(aTemplateInfo
)
1162 , m_aElementName(cacheTree
->getName())
1163 , m_aDataAddress(cacheTree
)
1166 Tree::build( _xStrategy
, cacheTree
->getRootNode(), nDepth
, aTemplateProvider
);
1168 //-----------------------------------------------------------------------------
1170 ElementTree::ElementTree( rtl::Reference
< data::TreeSegment
> const& pNewTree
,
1171 rtl::Reference
<Template
> aTemplate
,
1172 TemplateProvider
const& aTemplateProvider
)
1174 , m_aInstanceInfo(aTemplate
)
1175 , m_aOwnData(pNewTree
)
1178 throw Exception("ERROR: Provider can't create Element Instance From Template");
1179 m_aElementName
= pNewTree
->fragment
->getName();
1180 m_aDataAddress
= pNewTree
->fragment
;
1182 Tree::build( view::createDirectAccessStrategy(m_aOwnData
), m_aOwnData
->fragment
->nodes
, c_TreeDepthAll
, aTemplateProvider
);
1184 //-----------------------------------------------------------------------------
1186 ElementTree::~ElementTree()
1189 //-----------------------------------------------------------------------------
1191 bool ElementTree::isUpdatableSegment(Tree
& _rTree
)
1193 Tree
* pTree
= &_rTree
;
1195 while (ElementTree
* pElement
= dynamic_cast< ElementTree
* >(pTree
))
1197 if (pElement
->m_aOwnData
.is())
1199 OSL_ENSURE( pElement
->getContextTree()==NULL
||
1200 pElement
->getContextTree()->getViewBehavior() != pElement
->getViewBehavior(),
1201 "ElementTree with parent in same fragment should not own its data");
1205 pTree
= pElement
->getContextTree();
1209 OSL_ENSURE( false, "ElementTree without own data should have a parent");
1214 OSL_ENSURE( false, "Tree is not part of free-floating segment - cannot support direct update");
1218 //-----------------------------------------------------------------------------
1220 void ElementTree::disposeData()
1222 Tree::disposeData();
1225 //-----------------------------------------------------------------------------
1227 Path::Component
ElementTree::makeExtendedName(rtl::OUString
const& _aSimpleName
) const
1229 rtl::OUString aTypeName
= implGetOriginalName(ROOT
);
1231 OSL_ENSURE(this->isTemplateInstance(), "ElementTree: Cannot discover the type this instantiatiates");
1233 OSL_ENSURE(! this->isTemplateInstance() || this->getTemplate()->getName() == aTypeName
,
1234 "ElementTree: Type name does not match template");
1236 return Path::makeCompositeName(_aSimpleName
, aTypeName
);
1238 //-----------------------------------------------------------------------------
1240 // ownership handling
1241 //-----------------------------------------------------------------------------
1242 void ElementTree::rebuild(rtl::Reference
<view::ViewStrategy
> const & _aStrategy
, sharable::TreeFragment
* newTree
)
1244 Tree::rebuild(_aStrategy
, newTree
->getRootNode());
1245 m_aDataAddress
= newTree
;
1246 m_aElementName
= newTree
->getName();
1249 //-----------------------------------------------------------------------------
1250 /// transfer ownership to the given set
1251 // -----------------------------------------------------------------------------
1252 void ElementTree::attachTo(sharable::SetNode
* owningSet
, rtl::OUString
const& aElementName
)
1254 OSL_ENSURE(m_aOwnData
.is(), "ERROR: Cannot add a non-owned node to a subtree");
1256 if (m_aOwnData
.is())
1258 OSL_ENSURE(this->getSimpleRootName() == aElementName
,"ElementTree: Attaching with unexpected element name");
1259 m_aOwnData
->fragment
->setName(aElementName
);
1261 Tree
* pOwningTree
= this->getContextTree();
1262 OSL_ENSURE(pOwningTree
, "Element Tree Context must be set before attaching data");
1264 if (isUpdatableSegment(*pOwningTree
))
1266 // copy over to the new segment
1267 sharable::TreeFragment
* aNewElement
= data::buildTree(m_aOwnData
->fragment
);
1269 owningSet
->addElement(aNewElement
);
1271 rtl::Reference
<view::ViewStrategy
> xNewBehavior
= pOwningTree
->getViewBehavior();
1273 this->rebuild(xNewBehavior
,aNewElement
);
1276 OSL_ENSURE( false, "Cannot attach directly to new tree - no update access available");
1279 OSL_ASSERT(!m_aOwnData
.is());
1282 //-----------------------------------------------------------------------------
1284 /// tranfer ownership from the given set
1285 void ElementTree::detachFrom(sharable::SetNode
* owningSet
, rtl::OUString
const& aElementName
)
1287 OSL_ENSURE(!m_aOwnData
.is(),"ERROR: Cannot detach a already owned node from a subtree");
1288 OSL_ENSURE(this->getSimpleRootName() == aElementName
,"ElementTree: Detaching with unexpected element name");
1290 rtl::Reference
< view::ViewStrategy
> xOldStrategy
= this->getViewBehavior();
1291 OSL_ENSURE(xOldStrategy
.is(), "Element Tree Context must still have the old strategy when detaching data");
1294 // make a new segment with a copy of the data
1295 rtl::Reference
< data::TreeSegment
> aNewSegment
= data::TreeSegment::create( this->getOriginalTreeAccess() );
1297 OSL_ENSURE(aNewSegment
.is(),"ERROR: Could not create detached copy of elment data");
1299 this->takeTreeAndRebuild( aNewSegment
);
1301 sharable::TreeFragment
* aOldElement
= owningSet
->removeElement(aElementName
);
1302 OSL_ENSURE(aOldElement
!= NULL
,"ERROR: Detached node not found in the given subtree");
1304 data::destroyTree(aOldElement
);
1307 OSL_ENSURE(m_aOwnData
.is(),"ERROR: Could not create own data segment for detached node");
1309 //-----------------------------------------------------------------------------
1310 // -----------------------------------------------------------------------------
1311 // -----------------------------------------------------------------------------
1313 /// transfer ownership from the given owner
1314 void ElementTree::takeTreeBack(rtl::Reference
< data::TreeSegment
> const & _aDataSegment
)
1316 OSL_ENSURE(!m_aOwnData
.is(), "ERROR: Cannot take over a node - already owning");
1317 OSL_ENSURE(_aDataSegment
.is(), "ERROR: Cannot take over NULL tree segment");
1319 m_aOwnData
= _aDataSegment
;
1320 OSL_ENSURE(m_aOwnData
.is(), "ERROR: Could not take over data segment");
1322 m_aDataAddress
= m_aOwnData
->fragment
;
1323 m_aElementName
= m_aOwnData
->fragment
->getName();
1325 //-----------------------------------------------------------------------------
1327 /// transfer ownership from the given owner
1328 void ElementTree::takeTreeAndRebuild(rtl::Reference
< data::TreeSegment
> const & _aDataSegment
)
1330 OSL_ENSURE(!m_aOwnData
.is(), "ERROR: Cannot take over a node - already owning");
1331 OSL_ENSURE(_aDataSegment
.is(), "ERROR: Cannot take over NULL tree segment");
1332 this->rebuild(view::createDirectAccessStrategy(_aDataSegment
), _aDataSegment
->fragment
);
1333 m_aOwnData
= _aDataSegment
;
1335 //-----------------------------------------------------------------------------
1337 /// release ownership
1338 rtl::Reference
< data::TreeSegment
> ElementTree::releaseOwnedTree()
1340 OSL_ENSURE(m_aOwnData
.is(), "ERROR: Cannot release and rename a non-owned node");
1341 rtl::Reference
< data::TreeSegment
> aTree(m_aOwnData
);
1343 aTree
->fragment
->setName(m_aElementName
);
1346 //-----------------------------------------------------------------------------
1349 //-----------------------------------------------------------------------------
1351 /// renames the tree's root without concern for context consistency !
1352 void ElementTree::renameTree(rtl::OUString
const& aNewName
)
1354 m_aElementName
= aNewName
;
1356 //-----------------------------------------------------------------------------
1358 void ElementTree::moveTree(Tree
* pParentTree
, unsigned int nParentNode
)
1360 Tree::setContext(pParentTree
,nParentNode
);
1362 //-----------------------------------------------------------------------------
1364 void ElementTree::detachTree()
1366 Tree::clearContext();
1368 //-----------------------------------------------------------------------------
1370 //-----------------------------------------------------------------------------
1371 } // namespace configuration
1372 } // namespace configmgr