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
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 #ifndef CONFIGMGR_CONFIGNODEIMPL_HXX_
32 #define CONFIGMGR_CONFIGNODEIMPL_HXX_
35 #include "configpath.hxx"
36 #include "template.hxx"
37 #include "utility.hxx"
38 #include <rtl/ref.hxx>
39 #include <salhelper/simplereferenceobject.hxx>
40 #include <osl/diagnose.h>
42 #ifndef INCLUDED_VECTOR
44 #define INCLUDED_VECTOR
50 #ifndef INCLUDED_MEMORY
52 #define INCLUDED_MEMORY
57 namespace node
{ struct Attributes
; }
58 namespace sharable
{ union Node
; }
59 namespace view
{ class ViewStrategy
; }
60 namespace configuration
62 //-----------------------------------------------------------------------------
71 class TemplateProvider
;
73 class ValueElementNodeImpl
;
74 class ValueMemberNode
;
76 //-----------------------------------------------------------------------------
77 // WARNING: a similar item is in noderef.hxx
78 const unsigned int c_TreeDepthAll
= ~0u;
80 //-----------------------------------------------------------------------------
82 unsigned int& incDepth(unsigned int& rDepth
)
84 if (rDepth
!= c_TreeDepthAll
) ++rDepth
;
89 unsigned int& decDepth(unsigned int& rDepth
)
91 OSL_ENSURE(rDepth
!= 0,"Cannot decrement zero depth");
92 if (rDepth
!= c_TreeDepthAll
&& rDepth
!= 0) --rDepth
;
97 unsigned int childDepth(unsigned int nDepth
)
98 { return decDepth(nDepth
); }
101 unsigned int parentDepth(unsigned int nDepth
)
102 { return incDepth(nDepth
); }
105 unsigned int remainingDepth(unsigned int nOuterDepth
, unsigned int nRelativeDepth
)
107 OSL_ENSURE(nRelativeDepth
!= c_TreeDepthAll
,"RelativeDepth can't be infinite");
108 OSL_ENSURE(nRelativeDepth
<= nOuterDepth
,"ERROR: RelativeDepth is larger than enclosing depth");
110 unsigned int nInnerDepth
= (nOuterDepth
== c_TreeDepthAll
) ? nOuterDepth
:
111 (nRelativeDepth
< nOuterDepth
) ? nOuterDepth
-nRelativeDepth
:
115 //-------------------------------------------------------------------------
117 /// interface for a class that can be used to do some operation on a set of <type>NodeRef</type>s and <type>ValueRef</type>s.
120 /// returned from <method>handle</method> to indicate whether the operation is complete or should continue
121 enum Result
{ DONE
, CONTINUE
};
122 /// do the operation on <var>aNode</var>. needs to be implemented by concrete visitor classes
123 virtual Result
handle(rtl::Reference
< Tree
> const& aTree
, NodeRef
const& aNode
) = 0;
124 /// do the operation on <var>aValue</var>. needs to be implemented by concrete visitor classes
125 virtual Result
handle(rtl::Reference
< Tree
> const& aTree
, ValueRef
const& aValue
) = 0;
127 virtual ~NodeVisitor() {}
129 //-----------------------------------------------------------------------------
132 //-----------------------------------------------------------------------------
134 /** is the Implementation class for class <type>Node</type>, held inside a <type>Tree</type>.
135 <p> Implements some functionality common to all node types.
137 <p> Otherwise it provides (not really typesafe) access to a
138 <type scope='configmgr::configuration::NodeType>NodeImpl</type> which implements
139 functionality for a node of a given type
140 (as given by a <type scope='configmgr::configuration::NodeType>Enum</type> value).
145 rtl::Reference
<NodeImpl
> m_pSpecificNode
;
146 rtl::OUString m_aName_
; // cached for better performance
147 unsigned int m_nParent
;
149 NodeData(rtl::Reference
<NodeImpl
> const& aSpecificNodeImpl
, rtl::OUString
const& aName
, unsigned int nParent
);
151 void rebuild(rtl::Reference
<view::ViewStrategy
> const& _xNewStrategy
, sharable::Node
* _aNewData
);
152 // COMMON: information
153 rtl::OUString
getName() const { return m_aName_
; }
154 unsigned int getParent() const { return m_nParent
; }
158 // BASIC NODE: access to common attributes
159 NodeImpl
& nodeImpl() { return implGetNodeImpl(); }
160 NodeImpl
const & nodeImpl() const { return implGetNodeImpl(); }
162 // SET: access to child elements
163 bool isSetNode() const;
164 SetNodeImpl
& setImpl() { return implGetSetImpl(); }
165 SetNodeImpl
const& setImpl() const { return implGetSetImpl(); }
167 // VALUES: access to data
168 bool isValueElementNode() const;
169 ValueElementNodeImpl
& valueElementImpl() { return implGetValueImpl(); }
170 ValueElementNodeImpl
const& valueElementImpl() const { return implGetValueImpl(); }
172 // GROUP: access to children
173 bool isGroupNode() const;
174 GroupNodeImpl
& groupImpl() { return implGetGroupImpl(); }
175 GroupNodeImpl
const&groupImpl() const { return implGetGroupImpl(); }
179 sharable::Node
* getOriginalNodeAccess() const;
182 NodeImpl
& implGetNodeImpl() const;
183 SetNodeImpl
& implGetSetImpl() const;
184 GroupNodeImpl
& implGetGroupImpl() const ;
185 ValueElementNodeImpl
& implGetValueImpl() const ;
187 //-----------------------------------------------------------------------------
188 /** represents a hierarchy of config entries (identified by <type>NodeRef</type>s and <type>ValueRef</type>s)
190 <p>Examples for trees include</p>
192 <li>A module tree (for a specific set of parameters).</li>
193 <li>An updating tree (for a part of the whole).</li>
194 <li>A set element (updating or not), which could be detached.</li>
196 <p> Holds a list of <type>Node</type> which it allows to access by
197 <type>unsigned int</type> (which is basically a one-based index).
199 <p> Also provides for navigation to the context this tree is located in
202 class Tree
: public salhelper::SimpleReferenceObject
204 friend class view::ViewStrategy
;
207 /// creates a Tree for a detached, virgin tree
210 /// creates a Tree with a parent tree
211 Tree(Tree
& rParentTree
, unsigned int nParentNode
);
215 /// fills this Tree starting from _aRootNode, using the given factory and the tree's template provider
216 void build(rtl::Reference
<view::ViewStrategy
> const& _xStrategy
, sharable::Node
* _aRootNode
, unsigned int nDepth
, TemplateProvider
const& aTemplateProvider
);
218 void rebuild(rtl::Reference
<view::ViewStrategy
> const& _xNewStrategy
, sharable::Node
* _aNewData
);
221 // realeses the data this refers to
222 virtual void disposeData();
225 /// gets the path to the root node of this tree
226 AbsolutePath
getRootPath() const;
227 /// gets the tree of parent node of this tree
228 Tree
* getContextTree() { return m_pParentTree
; }
229 /// gets the tree of parent node of this tree
230 Tree
const *getContextTree() const { return m_pParentTree
; }
231 /// gets the offset of parent node of this tree within its tree
232 unsigned int getContextNode() const { return m_nParentNode
; }
234 // Node Collection information
235 /// checks whether <var>nNode</var> is a valid node offset in this tree
236 bool isValidNode(unsigned int nNode
) const;
238 bool isRootNode(NodeRef
const & node
) const;
240 NodeRef
getRootNode() const;
242 NodeRef
getContextNodeRef() const;
244 bool isValidValueNode(ValueRef
const & value
);
246 #if OSL_DEBUG_LEVEL > 0
247 bool isValidAnyNode(AnyNodeRef
const & node
);
250 /// checks whether the node has any element nodes (of its own)
251 bool hasElements(NodeRef
const & node
);
253 bool hasElement(NodeRef
const & node
, rtl::OUString
const & name
);
255 bool hasElement(NodeRef
const & node
, Path::Component
const & name
);
257 /** gets the element with the given name of the given node
258 <p>PRE: <code>hasElement(node, name)</code></p>
259 <p>If there is no such element, may return an empty node or
260 raise an exception (?)</p>
263 if name is not a valid child name for this node
265 rtl::Reference
< ElementTree
> getElement(
266 NodeRef
const & node
, rtl::OUString
const & name
);
268 /** gets the element with the given name of the given node, if it is
270 <p>PRE: <code>hasElement(node, name)</code></p>
271 <p>If there is no such element, may return an empty node or
272 raise an exception (?)</p>
273 <p>Caution: May miss existing children unless hasChild/getChild
274 has been called before.</p>
277 if name is not a valid child name for this node
279 rtl::Reference
< ElementTree
> getAvailableElement(
280 NodeRef
const & node
, rtl::OUString
const & name
);
282 /// checks whether the node has any child nodes (in this tree)
283 bool hasChildren(NodeRef
const & node
);
286 NodeRef
const & node
, rtl::OUString
const & name
);
288 bool hasChildNode(NodeRef
const & node
, rtl::OUString
const & name
);
290 bool hasChild(NodeRef
const & node
, rtl::OUString
const & name
);
292 /** gets the child value (in this tree) with the given name of the
294 <p>PRE: <code>hasChildValue(node, name)</code></p>
295 <P>If there is no such node, may return an empty node or raise
299 if <var>aName</var> is not a valid child name for this node
301 ValueRef
getChildValue(
302 NodeRef
const & node
, rtl::OUString
const & name
);
304 NodeRef
getChildNode(
305 NodeRef
const & node
, rtl::OUString
const & name
);
307 AnyNodeRef
getAnyChild(
308 NodeRef
const& node
, rtl::OUString
const & name
);
310 node::Attributes
getAttributes(NodeRef
const & node
);
312 node::Attributes
getAttributes(AnyNodeRef
const & node
);
314 node::Attributes
getAttributes(ValueRef
const & value
);
316 com::sun::star::uno::Type
getUnoType(ValueRef
const & value
);
318 /// return the parent of the given node (or an empty node, if it is
320 NodeRef
getParent(NodeRef
const & node
);
322 /// return the parent of the given value (or an empty node, if it is
324 NodeRef
getParent(ValueRef
const & value
);
326 AbsolutePath
getAbsolutePath(NodeRef
const & node
);
328 /// retrieves the current value for the given node, provided there
329 /// is one and it is available (only works for value nodes)
330 com::sun::star::uno::Any
getNodeValue(ValueRef
const & value
);
332 /// checks whether the given node has a default value (only works
334 bool hasNodeDefault(ValueRef
const & value
);
336 /// checks whether the given node assumes its default value (only
337 /// works for value nodes)
338 bool isNodeDefault(ValueRef
const & value
);
340 /// checks whether the given node has a default state
341 bool hasNodeDefault(NodeRef
const & node
);
343 /// checks whether the given node assumes its default state
344 bool isNodeDefault(NodeRef
const & node
);
346 /// checks whether the given node has a default state
347 bool hasNodeDefault(AnyNodeRef
const & node
);
349 /// checks whether the given node assumes its default state
350 bool isNodeDefault(AnyNodeRef
const & node
);
352 /// checks whether the default values are available for the children
353 /// of the given node (if applicable)
354 bool areValueDefaultsAvailable(NodeRef
const & node
);
356 /// retrieves the default value for the given node, provided there
357 /// is one and it is available (only works for value nodes)
358 com::sun::star::uno::Any
getNodeDefaultValue(
359 ValueRef
const & value
);
363 /// lists any pending changes on this tree
364 bool collectChanges(NodeChanges
& changes
);
367 NodeChange
& change
, NodeRef
const & node
, bool local
);
370 NodeChanges
& changes
, NodeRef
const & node
, bool local
);
372 NodeVisitor::Result
visit(
373 NodeRef
const & node
, NodeVisitor
& visitor
)
374 { return visitor
.handle(this, node
); }
376 NodeVisitor::Result
visit(
377 ValueRef
const & value
, NodeVisitor
& visitor
)
378 { return visitor
.handle(this, value
); }
380 /** lets the given visitor visit the child nodes of the given node
382 The order in which nodes are visited is repeatable (but
383 currently unspecified). Visits nodes until NodeVisitor::DONE is
384 returned, then returns NodeVisitor::DONE. If all visits return
385 NodeVisitor::CONTINUE, returns NodeVisitor::CONTINUE. If no
386 children are present, returns NodeVisitor::CONTINUE.
388 NodeVisitor::Result
dispatchToChildren(
389 NodeRef
const & node
, NodeVisitor
& visitor
);
391 NodeRef
getNode(unsigned int offset
) const;
393 rtl::Reference
< Template
> extractElementInfo(NodeRef
const & node
);
395 /// gets the depth that is available in this tree (due to the original request)
396 unsigned int getAvailableDepth() const { return m_nDepth
; }
398 /// gets the depth that is available in this tree within the given node
399 unsigned int getRemainingDepth(unsigned int nNode
) const
400 { return remainingDepth(getAvailableDepth(),depthTo(nNode
)); }
402 // Node Collection navigation
403 /** gets the simple name of the node <var>nNode</var>
404 <p>PRE: <code>isValidNode(nNode)</code>
407 rtl::OUString
getSimpleNodeName(unsigned int nNode
) const;
409 /** gets the simple name of the root node (i.e. of the tree as a whole)
411 virtual rtl::OUString
getSimpleRootName() const;
413 /** gets the full name of the root node
415 Path::Component
getExtendedRootName() const;
417 /** gets the number of hierarchy levels from the root node to node <var>nNode</var>
419 <p>In particular <code>depthTo(N) == 0</code> if <code>N == root()</code>
421 <p>PRE: <code>isValidNode(nNode)</code>
424 unsigned int depthTo(unsigned int nNode
) const;
426 /// append the local path (relative to root) to a node to a collection of names
427 void prependLocalPathTo(unsigned int nNode
, Path::Rep
& rNames
);
429 // check whether defaults are available
430 bool hasDefaults(unsigned int _nNode
) const;
432 enum { ROOT
= 1 }; /// base of <type>unsigned int</type>s used in this class
434 /** gets the <type>unsigned int</type> of the parent node <var>nNode</var> in this tree
435 or 0 (zero) if it is the root node
436 <p>PRE: <code>isValidNode(nNode)</code>
439 unsigned int parent_(unsigned int nNode
) const;
441 // Node iteration and access
442 /** gets the <type>unsigned int</type> of the first child node
443 of node <var>nParent</var> in this tree (in list order)
444 or 0 (zero) if it has no children in this tree
445 <p>PRE: <code>isValidNode(nParent)</code>
448 unsigned int firstChild_ (unsigned int nParent
) const;
450 /** gets the <type>unsigned int</type> of the first child node
451 of node <var>nParent</var> that is after
452 node <var>nNode</var> in this tree (in list order)
453 or 0 (zero) if there is no such node
454 <p>if <code>nStartAfter == 0</code> searching starts at the beginning
456 <p>PRE: <code>isValidNode(nParent)</code>
458 <p>PRE: <code>isValidNode(nStartAfter) || nStartAfter == 0</code>
461 unsigned int findNextChild_(unsigned int nParent
, unsigned int nStartAfter
) const;
463 /** gets the <type>unsigned int</type> of the first (and only) child node
464 of node <var>nParent</var> in this tree (in list order)
465 where the name of the node is <var>aName</var>,
466 or 0 (zero) if there is no such node
467 <p>PRE: <code>isValidNode(nParent)</code>
470 unsigned int findChild_(unsigned int nParent
, rtl::OUString
const& aName
) const;
472 // Node Collection access
473 /// get the number of nodes in this tree
474 unsigned int nodeCount() const;
476 /// get the <type>NodeData</type> for node <var>nNode</var> in this tree
477 NodeData
* nodeData(unsigned int nNode
);
478 /// get the <type>NodeData</type> for node <var>nNode</var> in this tree
479 NodeData
const* nodeData(unsigned int nNode
) const;
480 /// get the <type>NodeData</type> for node <var>nNode</var> in this tree
481 NodeImpl
& nodeImpl(unsigned int nNode
) { return nodeData(nNode
)->nodeImpl(); }
482 /// get the <type>NodeData</type> for node <var>nNode</var> in this tree
483 NodeImpl
const& nodeImpl(unsigned int nNode
) const { return nodeData(nNode
)->nodeImpl(); }
485 unsigned int nodeOffset(NodeData
const & rNodeData
) const;
488 rtl::Reference
< view::ViewStrategy
> getViewBehavior() const;
491 /* // implementation of commit protocol
494 void implCommitDirectFrom(unsigned int nNode);
496 void implRebuild(unsigned int nNode
, sharable::Node
* _aNewData
);
499 /// set a new parent context for this tree
500 void setContext(Tree
* pParentTree
, unsigned int nParentNode
);
501 /// set no-parent context for this tree
504 inline // is protected and should be used only in the implementation
505 rtl::OUString
implGetOriginalName(unsigned int nNode
) const;
508 /// get the full name of the root of this tree
509 virtual Path::Component
doGetRootName() const = 0;
511 /// prepend the absolute path to the root of this tree (no context use)
512 virtual void doFinishRootPath(Path::Rep
& rPath
) const = 0;
514 ValueMemberNode
getMemberNode(ValueRef
const & value
);
516 rtl::Reference
<view::ViewStrategy
> m_xStrategy
;
517 std::vector
<NodeData
> m_aNodes
;
519 unsigned int m_nParentNode
;
520 unsigned int m_nDepth
;
522 /// prepend the absolute path to the root of this tree (using context if present)
523 void implPrependRootPath(Path::Rep
& rPath
) const;
525 friend class TreeImplBuilder
;
528 /// checks, if tree represents a real tree
529 bool isEmpty(Tree
* tree
);
530 //-----------------------------------------------------------------------------
532 class ElementTree
: public Tree
536 /// creates a Tree for a detached, virgin instance of <var>aTemplate</var> (always will be direct)
537 ElementTree(rtl::Reference
< data::TreeSegment
> const& _aElementData
, rtl::Reference
<Template
> aTemplate
, TemplateProvider
const& aTemplateProvider
);
539 /** creates a Tree with a parent tree, that (supposedly)
540 is an instance of <var>aTemplateInfo</var>
542 ElementTree(rtl::Reference
<view::ViewStrategy
> const& _xStrategy
,
543 Tree
& rParentTree
, unsigned int nParentNode
,
544 sharable::TreeFragment
* dataTree
, unsigned int nDepth
,
545 rtl::Reference
<Template
> aTemplateInfo
,
546 TemplateProvider
const& aTemplateProvider
);
548 /** creates a Tree with no parent node, that (supposedly)
549 is an instance of <var>aTemplateInfo</var>
551 ElementTree(rtl::Reference
<view::ViewStrategy
> const& _xStrategy
,
552 sharable::TreeFragment
* dataTree
, unsigned int nDepth
,
553 rtl::Reference
<Template
> aTemplateInfo
,
554 TemplateProvider
const& aTemplateProvider
);
558 // realeses the data this refers to
559 virtual void disposeData();
563 void rebuild(rtl::Reference
<view::ViewStrategy
> const& _xNewStrategy
, sharable::TreeFragment
* newData
);
566 sharable::TreeFragment
* getOriginalTreeAccess() const { return m_aDataAddress
; }
569 virtual rtl::OUString
getSimpleRootName() const;
570 /// checks whether this is an instance of a known template
571 bool isTemplateInstance() const { return !!m_aInstanceInfo
.is(); }
572 /// checks whether this is an instance of the given template
573 bool isInstanceOf(rtl::Reference
<Template
> const& aTemplateInfo
) const
574 { return m_aInstanceInfo
== aTemplateInfo
&& aTemplateInfo
.is(); }
575 /// retrieves the template that this is an instance of
576 rtl::Reference
<Template
> getTemplate() const { return m_aInstanceInfo
; }
577 /// makes a complete name from a simple name and template information
578 Path::Component
makeExtendedName(rtl::OUString
const& aSimpleName
) const;
580 // node control operation
581 /// check if this is a free-floating tree
582 bool isFree() const { return m_aOwnData
.is(); }
583 /// transfer ownership to the given set
584 void attachTo(sharable::SetNode
* updatableSetNode
, rtl::OUString
const& aElementName
);
585 /// tranfer ownership from the given set
586 void detachFrom(sharable::SetNode
* updatableSetNode
, rtl::OUString
const& aElementName
);
588 /// take ownership of the given tree (which must not already be the one in use)
589 void takeTreeAndRebuild(rtl::Reference
< data::TreeSegment
> const& _aElementData
);
590 /// take ownership of the given tree (which must already be the one in use)
591 void takeTreeBack(rtl::Reference
< data::TreeSegment
> const& _aElementData
);
593 /// release ownership
594 rtl::Reference
< data::TreeSegment
> releaseOwnedTree();
597 /// set a new root name
598 void renameTree(rtl::OUString
const& aNewName
);
599 /// set a new parent context for this tree
600 void moveTree(Tree
* pParentTree
, unsigned int nParentNode
);
601 /// set no-parent context for this tree
605 static bool isUpdatableSegment(Tree
& _rTree
);
607 virtual Path::Component
doGetRootName() const;
609 virtual void doFinishRootPath(Path::Rep
& rPath
) const;
611 rtl::Reference
<Template
> const m_aInstanceInfo
;
612 rtl::OUString m_aElementName
;
613 sharable::TreeFragment
* m_aDataAddress
;
614 rtl::Reference
< data::TreeSegment
> m_aOwnData
;
616 //-----------------------------------------------------------------------------
618 bool Tree::isValidNode(unsigned int nNode
) const
620 return ROOT
<= nNode
&& nNode
< nodeCount() + ROOT
;
622 //---------------------------------------------------------------------
624 unsigned int Tree::nodeCount() const
626 return m_aNodes
.size();
628 //---------------------------------------------------------------------
630 NodeData
* Tree::nodeData(unsigned int nNode
)
632 if (nNode
== 0) return NULL
;
633 OSL_ASSERT(isValidNode(nNode
));
634 return &m_aNodes
[nNode
- ROOT
];
636 //---------------------------------------------------------------------
638 NodeData
const* Tree::nodeData(unsigned int nNode
) const
640 if (nNode
== 0) return NULL
;
641 OSL_ASSERT(isValidNode(nNode
));
642 return &m_aNodes
[nNode
- ROOT
];
644 //---------------------------------------------------------------------
646 unsigned int Tree::nodeOffset(NodeData
const & rNode
) const
648 unsigned int nOffset
= ROOT
+ (&rNode
- &m_aNodes
[0]);
649 OSL_ASSERT(isValidNode(nOffset
));
653 //-----------------------------------------------------------------------------
654 // helper for other impl classes
655 //-----------------------------------------------------------------------------
656 #if OSL_DEBUG_LEVEL > 0
660 com::sun::star::uno::Type
getUnoType(rtl::Reference
< ElementTree
> const& aElement
);
663 //-----------------------------------------------------------------------------
665 //-----------------------------------------------------------------------------
668 #endif // CONFIGMGR_CONFIGNODEIMPL_HXX_