/************************************************************************* * * 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.hxx,v $ * $Revision: 1.27 $ * * 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 * * for a copy of the LGPLv3 License. * ************************************************************************/ #ifndef CONFIGMGR_CONFIGNODEIMPL_HXX_ #define CONFIGMGR_CONFIGNODEIMPL_HXX_ #include "change.hxx" #include "nodeimpl.hxx" #include "configpath.hxx" #include "template.hxx" #include "treeaccessor.hxx" #include "utility.hxx" #include #include #ifndef INCLUDED_VECTOR #include #define INCLUDED_VECTOR #endif #ifndef INCLUDED_MAP #include #define INCLUDED_MAP #endif #ifndef INCLUDED_MEMORY #include #define INCLUDED_MEMORY #endif namespace configmgr { class INode; class ISubtree; class Change; class SubtreeChange; namespace view { class ViewStrategy; class ViewTreeAccess; } namespace node { struct Attributes; } namespace configuration { //----------------------------------------------------------------------------- typedef com::sun::star::uno::Any UnoAny; //----------------------------------------------------------------------------- class TreeImpl; class TemplateProvider; //----------------------------------------------------------------------------- typedef unsigned int NodeOffset; typedef unsigned int TreeDepth; // WARNING: a similar item is in noderef.hxx const TreeDepth c_TreeDepthAll = ~0u; //----------------------------------------------------------------------------- inline TreeDepth& incDepth(TreeDepth& rDepth) { if (rDepth != c_TreeDepthAll) ++rDepth; return rDepth; } inline TreeDepth& decDepth(TreeDepth& rDepth) { OSL_ENSURE(rDepth != 0,"Cannot decrement zero depth"); if (rDepth != c_TreeDepthAll && rDepth != 0) --rDepth; return rDepth; } inline TreeDepth childDepth(TreeDepth nDepth) { return decDepth(nDepth); } inline TreeDepth parentDepth(TreeDepth nDepth) { return incDepth(nDepth); } inline TreeDepth remainingDepth(TreeDepth nOuterDepth, TreeDepth nRelativeDepth) { OSL_ENSURE(nRelativeDepth != c_TreeDepthAll,"RelativeDepth can't be infinite"); OSL_ENSURE(nRelativeDepth <= nOuterDepth,"ERROR: RelativeDepth is larger than enclosing depth"); TreeDepth nInnerDepth = (nOuterDepth == c_TreeDepthAll) ? nOuterDepth : (nRelativeDepth < nOuterDepth) ? nOuterDepth-nRelativeDepth : 0; return nInnerDepth; } //----------------------------------------------------------------------------- // class Node Impl //----------------------------------------------------------------------------- /** is the Implementation class for class Node, held inside a Tree.

Implements some functionality common to all node types.

Otherwise it provides (not really typesafe) access to a Enum value).

*/ class NodeData { rtl::Reference m_pSpecificNode; Name m_aName_; // cached for better performance NodeOffset m_nParent; public: NodeData(rtl::Reference const& aSpecificNodeImpl, Name const& aName, NodeOffset nParent); void rebuild(rtl::Reference const& _xNewStrategy, data::NodeAccess const & _aNewData); // COMMON: information Name getName() const { return m_aName_; } NodeOffset getParent() const { return m_nParent; } // change management public: // BASIC NODE: access to common attributes NodeImpl & nodeImpl() { return implGetNodeImpl(); } NodeImpl const & nodeImpl() const { return implGetNodeImpl(); } // SET: access to child elements bool isSetNode() const; SetNodeImpl& setImpl() { return implGetSetImpl(); } SetNodeImpl const& setImpl() const { return implGetSetImpl(); } // VALUES: access to data bool isValueElementNode() const; ValueElementNodeImpl& valueElementImpl() { return implGetValueImpl(); } ValueElementNodeImpl const& valueElementImpl() const { return implGetValueImpl(); } // GROUP: access to children bool isGroupNode() const; GroupNodeImpl& groupImpl() { return implGetGroupImpl(); } GroupNodeImpl const&groupImpl() const { return implGetGroupImpl(); } // access helper public: data::NodeAccess getOriginalNodeAccess() const { return data::NodeAccess(m_pSpecificNode->getOriginalNodeAddress()); } private: NodeImpl& implGetNodeImpl() const; SetNodeImpl& implGetSetImpl() const; GroupNodeImpl& implGetGroupImpl() const ; ValueElementNodeImpl& implGetValueImpl() const ; }; //----------------------------------------------------------------------------- class RootTreeImpl; // for 'dynamic-casting' class ElementTreeImpl; // for 'dynamic-casting' typedef rtl::Reference ElementTreeHolder; // see also setnodeimpl.hxx typedef std::vector< ElementTreeHolder > ElementList; // see also setnodeimpl.hxx /** is the Implementation class for class Tree.

Holds a list of Node which it allows to access by NodeOffset (which is basically a one-based index).

Also provides for navigation to the context this tree is located in

*/ class TreeImpl : public configmgr::SimpleReferenceObject { friend class view::ViewStrategy; friend class TreeSetNodeImpl; // friend class DeferredSetNodeImpl; public: /// the type of the internal list of Node typedef std::vector NodeList; protected: // Construction /// creates a TreeImpl for a detached, virgin tree explicit TreeImpl( ); /// creates a TreeImpl with a parent tree TreeImpl(TreeImpl& rParentTree, NodeOffset nParentNode); /// fills this TreeImpl starting from _aRootNode, using the given factory and the tree's template provider void build(rtl::Reference const& _xStrategy, data::NodeAccess const& _aRootNode, TreeDepth nDepth, TemplateProvider const& aTemplateProvider); void rebuild(rtl::Reference const& _xNewStrategy, data::NodeAccess const & _aNewData); public: /// destroys a TreeImpl virtual ~TreeImpl(); // realeses the data this refers to virtual void disposeData(); // Context Access /// gets the path to the root node of this tree AbsolutePath getRootPath() const; /// gets the tree of parent node of this tree TreeImpl* getContextTree() { return m_pParentTree; } /// gets the tree of parent node of this tree TreeImpl const *getContextTree() const { return m_pParentTree; } /// gets the offset of parent node of this tree within its tree NodeOffset getContextNode() const { return m_nParentNode; } // Node Collection information /// checks whether nNode is a valid node offset in this tree bool isValidNode(NodeOffset nNode) const; /// gets the depth that is available in this tree (due to the original request) TreeDepth getAvailableDepth() const { return m_nDepth; } /// gets the depth that is available in this tree within the given node TreeDepth getRemainingDepth(NodeOffset nNode) const { return remainingDepth(getAvailableDepth(),depthTo(nNode)); } // Node Collection navigation /** gets the simple Name of the node nNode

PRE: isValidNode(nNode)

*/ Name getSimpleNodeName(NodeOffset nNode) const; /** gets the simple Name of the root node (i.e. of the tree as a whole) */ virtual Name getSimpleRootName() const; /** gets the full name of the root node */ Path::Component getExtendedRootName() const; /** gets the number of hierarchy levels from the root node to node nNode in this tree

In particular depthTo(N) == 0 if N == root()

PRE: isValidNode(nNode)

*/ TreeDepth depthTo(NodeOffset nNode) const; /// append the local path (relative to root) to a node to a collection of names void prependLocalPathTo(NodeOffset nNode, Path::Rep& rNames); // check whether defaults are available bool hasDefaults(NodeOffset _nNode) const; public: /// gets the NodeOffset of the root node in this tree NodeOffset root_() const { return m_nRoot; } /** gets the NodeOffset of the parent node nNode in this tree or 0 (zero) if it is the root node

PRE: isValidNode(nNode)

*/ NodeOffset parent_(NodeOffset nNode) const; // Node iteration and access /** gets the NodeOffset of the first child node of node nParent in this tree (in list order) or 0 (zero) if it has no children in this tree

PRE: isValidNode(nParent)

*/ NodeOffset firstChild_ (NodeOffset nParent) const; /** gets the NodeOffset of the first child node of node nParent that is after node nNode in this tree (in list order) or 0 (zero) if there is no such node

if nStartAfter == 0 searching starts at the beginning

PRE: isValidNode(nParent)

PRE: isValidNode(nStartAfter) || nStartAfter == 0

*/ NodeOffset findNextChild_(NodeOffset nParent, NodeOffset nStartAfter) const; /** gets the NodeOffset of the first (and only) child node of node nParent in this tree (in list order) where the name of the node is aName, or 0 (zero) if there is no such node

PRE: isValidNode(nParent)

*/ NodeOffset findChild_(NodeOffset nParent, Name const& aName) const; // Node Collection access /// get the number of nodes in this tree NodeOffset nodeCount() const; /// get the NodeData for node nNode in this tree NodeData* nodeData(NodeOffset nNode); /// get the NodeData for node nNode in this tree NodeData const* nodeData(NodeOffset nNode) const; /// get the NodeData for node nNode in this tree NodeImpl& nodeImpl(NodeOffset nNode) { return nodeData(nNode)->nodeImpl(); } /// get the NodeData for node nNode in this tree NodeImpl const& nodeImpl(NodeOffset nNode) const { return nodeData(nNode)->nodeImpl(); } NodeOffset nodeOffset(NodeData const & rNodeData) const; ElementTreeImpl * asElementTree(); ElementTreeImpl const* asElementTree() const; // Behavior rtl::Reference< view::ViewStrategy > getViewBehavior() const; protected: // immediate commit /* // implementation of commit protocol void commitDirect(); void implCommitDirectFrom(NodeOffset nNode); */ void implRebuild(NodeOffset nNode, data::NodeAccess const & _aNewData); protected: /// set a new parent context for this tree void setContext(TreeImpl* pParentTree, NodeOffset nParentNode); /// set no-parent context for this tree void clearContext(); inline // is protected and should be used only in the implementation Name implGetOriginalName(NodeOffset nNode) const; private: virtual RootTreeImpl const* doCastToRootTree() const = 0; virtual ElementTreeImpl const* doCastToElementTree() const = 0; /// get the full name of the root of this tree virtual Path::Component doGetRootName() const = 0; /// prepend the absolute path to the root of this tree (no context use) virtual void doFinishRootPath(Path::Rep& rPath) const = 0; rtl::Reference m_xStrategy; NodeList m_aNodes; TreeImpl* m_pParentTree; NodeOffset m_nParentNode; TreeDepth m_nDepth; enum { m_nRoot = 1 }; /// base of NodeOffsets used in this class /// prepend the absolute path to the root of this tree (using context if present) void implPrependRootPath(Path::Rep& rPath) const; friend class TreeImplBuilder; }; //----------------------------------------------------------------------------- class ElementTreeImpl : public TreeImpl { public: /// creates a TreeImpl for a detached, virgin instance of aTemplate (always will be direct) ElementTreeImpl( data::TreeSegment const& _aElementData, TemplateHolder aTemplate, TemplateProvider const& aTemplateProvider ); /** creates a TreeImpl with a parent tree, that (supposedly) is an instance of aTemplateInfo */ ElementTreeImpl(rtl::Reference const& _xStrategy, TreeImpl& rParentTree, NodeOffset nParentNode, data::TreeAccessor const& _aDataTree, TreeDepth nDepth, TemplateHolder aTemplateInfo, TemplateProvider const& aTemplateProvider ); /** creates a TreeImpl with no parent node, that (supposedly) is an instance of aTemplateInfo */ ElementTreeImpl(rtl::Reference const& _xStrategy, data::TreeAccessor const& _aDataTree, TreeDepth nDepth, TemplateHolder aTemplateInfo, TemplateProvider const& aTemplateProvider ); ~ElementTreeImpl(); // realeses the data this refers to virtual void disposeData(); // rebuilding using TreeImpl::rebuild; void rebuild(rtl::Reference const& _xNewStrategy, data::TreeAccessor const & _aNewData); // data access data::TreeAccessor getOriginalTreeAccess() const { return data::TreeAccessor(m_aDataAddress); } // Tree information virtual Name getSimpleRootName() const; /// checks whether this is an instance of a known template bool isTemplateInstance() const { return !!m_aInstanceInfo.is(); } /// checks whether this is an instance of the given template bool isInstanceOf(TemplateHolder const& aTemplateInfo) const { return m_aInstanceInfo == aTemplateInfo && aTemplateInfo.is(); } /// retrieves the template that this is an instance of TemplateHolder getTemplate() const { return m_aInstanceInfo; } /// makes a complete name from a simple name and template information Path::Component makeExtendedName(Name const& aSimpleName) const; // node control operation /// check if this is a free-floating tree bool isFree() const { return m_aOwnData.is(); } /// transfer ownership to the given set void attachTo(data::SetNodeAccess const & _aUpdatableSetNode, Name const& aElementName); /// tranfer ownership from the given set void detachFrom(data::SetNodeAccess const & _aUpdatableSetNode, Name const& aElementName); /// take ownership of the given tree (which must not already be the one in use) void takeTreeAndRebuild(data::TreeSegment const& _aElementData); /// take ownership of the given tree (which must already be the one in use) void takeTreeBack(data::TreeSegment const& _aElementData); /// release ownership data::TreeSegment releaseOwnedTree(); // context operation /// set a new root name void renameTree(Name const& aNewName); /// set a new parent context for this tree void moveTree(TreeImpl* pParentTree, NodeOffset nParentNode); /// set no-parent context for this tree void detachTree(); private: static bool isUpdatableSegment(TreeImpl& _rTree); virtual RootTreeImpl const* doCastToRootTree() const; virtual ElementTreeImpl const* doCastToElementTree() const; virtual Path::Component doGetRootName() const; virtual void doFinishRootPath(Path::Rep& rPath) const; private: TemplateHolder const m_aInstanceInfo; Name m_aElementName; data::TreeAddress m_aDataAddress; data::TreeSegment m_aOwnData; }; //----------------------------------------------------------------------------- inline NodeImpl& NodeData::implGetNodeImpl() const { OSL_ASSERT(m_pSpecificNode != 0); return *m_pSpecificNode; } //----------------------------------------------------------------------------- inline bool TreeImpl::isValidNode(NodeOffset nNode) const { return m_nRoot <= nNode && nNode < nodeCount() +m_nRoot; } //--------------------------------------------------------------------- inline NodeOffset TreeImpl::nodeCount() const { return m_aNodes.size(); } //--------------------------------------------------------------------- inline NodeData* TreeImpl::nodeData(NodeOffset nNode) { if (nNode == 0) return NULL; OSL_ASSERT(isValidNode(nNode)); return &m_aNodes[nNode-root_()]; } //--------------------------------------------------------------------- inline NodeData const* TreeImpl::nodeData(NodeOffset nNode) const { if (nNode == 0) return NULL; OSL_ASSERT(isValidNode(nNode)); return &m_aNodes[nNode-root_()]; } //--------------------------------------------------------------------- inline NodeOffset TreeImpl::nodeOffset(NodeData const & rNode) const { NodeOffset nOffset = root_() + (&rNode - &m_aNodes[0]); OSL_ASSERT(isValidNode(nOffset)); return nOffset; } //----------------------------------------------------------------------------- // helper for other impl classes //----------------------------------------------------------------------------- class Tree; class TreeRef; class NodeRef; class ValueRef; class AnyNodeRef; class NodeID; class ValueMemberNode; //----------------------------------------------------------------------------- /// is a hack to avoid too many friend declarations in public headers class TreeImplHelper { public: static NodeRef makeNode(NodeOffset nOffset, TreeDepth nDepth); static NodeRef makeNode(TreeImpl& rTree, NodeOffset nOffset); static NodeRef makeNode(NodeID const& aNodeID); static ValueRef makeValue(Name const& aName, NodeOffset nParentOffset); static TreeImpl* impl(Tree const& aTree); static TreeImpl* impl(TreeRef const& aTree); static NodeData* nodeData(NodeRef const& aNode); static NodeOffset offset(NodeRef const& aNode); static NodeOffset parent_offset(ValueRef const& aNode); static Name value_name(ValueRef const& aNode); static ValueMemberNode member_node(Tree const & _aTree,ValueRef const& aValue); static TreeImpl* tree(NodeID const& aNodeID); static NodeOffset offset(NodeID const& aNodeID); }; //----------------------------------------------------------------------------- class ElementTree; //----------------------------------------------------------------------------- #if OSL_DEBUG_LEVEL > 0 struct ElementHelper { static UnoType getUnoType(ElementTree const& aElement); }; #endif //----------------------------------------------------------------------------- } //----------------------------------------------------------------------------- } #endif // CONFIGMGR_CONFIGNODEIMPL_HXX_