/************************************************************************* * * $RCSfile: noderef.hxx,v $ * * $Revision: 1.9 $ * * last change: $Author: jb $ $Date: 2001-06-20 20:19:26 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses * * - GNU Lesser General Public License Version 2.1 * - Sun Industry Standards Source License Version 1.1 * * Sun Microsystems Inc., October, 2000 * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2000 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * * Sun Industry Standards Source License Version 1.1 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.1 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://www.openoffice.org/license.html. * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2000 by Sun Microsystems, Inc. * * All Rights Reserved. * * Contributor(s): _______________________________________ * * ************************************************************************/ #ifndef CONFIGMGR_CONFIGNODE_HXX_ #define CONFIGMGR_CONFIGNODE_HXX_ #include "apitypes.hxx" #include "configexcept.hxx" #include "configpath.hxx" #include #ifndef _OSL_DIAGNOSE_H_ #include #endif namespace configmgr { class INode; class ISynchronizedData; namespace configapi { class Factory; } namespace configuration { //------------------------------------------------------------------------- class Name; class AbsolutePath; class RelativePath; struct Attributes; class NodeChange; class NodeChanges; class NodeChangesTree; //------------------------------------------------------------------------- namespace argument { struct NoValidate; } typedef com::sun::star::uno::Type UnoType; typedef com::sun::star::uno::Any UnoAny; //------------------------------------------------------------------------- class NodeRef; class ValueRef; class AnyNodeRef; class ElementRef; class NodeID; class Tree; class Node; class TreeImpl; typedef unsigned int NodeOffset; typedef unsigned int TreeDepth; const TreeDepth C_TreeDepthAll = ~0u; //------------------------------------------------------------------------- /// interface for a class that can be used to do some operation on a set of NodeRefs and ValueRefs. struct NodeVisitor { /// returned from handle to indicate whether the operation is complete or should continue enum Result { DONE, CONTINUE }; /// do the operation on aNode. needs to be implemented by concrete visitor classes virtual Result handle(Tree const& aTree, NodeRef const& aNode) = 0; /// do the operation on aValue. needs to be implemented by concrete visitor classes virtual Result handle(Tree const& aTree, ValueRef const& aValue) = 0; }; //------------------------------------------------------------------------- /// represents a inner node position in some tree class NodeRef { public: /// constructs an empty (invalid) node NodeRef(); /// copy a node (with reference semantics) NodeRef(NodeRef const& rOther); /// copy a node (with reference semantics) NodeRef& operator=(NodeRef const& rOther); void swap(NodeRef& rOther); ~NodeRef(); /// checks, if this represents an existing node inline bool isValid() const; private: friend class Tree; friend class TreeImplHelper; friend class AnyNodeRef; NodeRef(Node* pImpl, NodeOffset nPos, TreeDepth nDepth); private: Node* m_pImpl; NodeOffset m_nPos; TreeDepth m_nDepth; }; //------------------------------------------------------------------------- /** represents a hierarchy of config entries (identified by NodeRefs and ValueRefs)

Examples for trees include

  • A module tree (for a specific set of parameters).
  • An updating tree (for a part of the whole).
  • A set element (updating or not), which could be detached.
  • */ class Tree { public: /// create a tree with a given implementation Tree(TreeImpl* pImpl); /// copy a tree (with reference semantics) Tree(Tree const& rOther); /// copy a tree (with reference semantics) Tree& operator=(Tree const& rOther); void swap(Tree& rOther); ~Tree(); /// checks, if this represents an real tree bool isEmpty() const; // releases the data this tree operates on void disposeData(); /// retrieves the number of immediately contained (subtree) nodes NodeOffset getContainedInnerNodeCount() const; /// checks whether the node aNode is a valid inner node in this tree. bool isValidNode(AnyNodeRef const& aNode) const; /// checks whether the node aNode is a valid inner node in this tree. bool isValidNode(NodeRef const& aNode) const; /// checks whether the node aNode is a valid value node in this tree. bool isValidNode(ValueRef const& aNode) const; /// checks whether the node aNode has any element nodes (of its own). bool hasElements(NodeRef const& aNode) const; /// checks whether the node aNode has a element node named aName. bool hasElement(NodeRef const& aNode, Name const& aName) const; /** gets the element named aName of node aNode.

    PRE: hasElement(aNode,aName) == true

    If there is no such element, may return an empty node or raise an exception (?)

    @throws InvalidName if aName is not a valid child name for this node */ ElementRef getElement(NodeRef const& aNode, Name const& aName) const; /** gets the element named aName of node aNode, if it is available.

    PRE: hasElement(aNode,aName) == true

    If there is no such element, may return an empty node or raise an exception (?)

    Caution: May miss existing children unless hasChild/getChild has been called before.

    @throws InvalidName if aName is not a valid child name for this node */ ElementRef getAvailableElement(NodeRef const& aNode, Name const& aName) const; /// checks whether the node aNode has any child value (in this tree). bool hasChildValues(NodeRef const& aNode) const; /// checks whether the node aNode has any child subtrees (in this tree). bool hasChildNodes(NodeRef const& aNode) const; /// checks whether the node aNode has any child nodes (in this tree). bool hasChildren(NodeRef const& aNode) const; /// checks whether the node aNode has a child value (in this tree) named aName. bool hasChildValue(NodeRef const& aNode, Name const& aName) const; /// checks whether the node aNode has a child subtree (in this tree) named aName. bool hasChildNode(NodeRef const& aNode, Name const& aName) const; /// checks whether the node aNode has a child node (in this tree) named aName. bool hasChild(NodeRef const& aNode, Name const& aName) const; /** gets the child value (in this tree) named aName of node aNode.

    PRE: hasChildValue(aNode,aName) == true

    If there is no such node, may return an empty node or raise an exception (?)

    @throws InvalidName if aName is not a valid child name for this node */ ValueRef getChildValue(NodeRef const& aNode, Name const& aName) const; /** gets the child value (in this tree) named aName of node aNode.

    PRE: hasChildNode(aNode,aName) == true

    If there is no such node, may return an empty node or raise an exception (?)

    @throws InvalidName if aName is not a valid child name for this node */ NodeRef getChildNode(NodeRef const& aNode, Name const& aName) const; /** gets the child value (in this tree) named aName of node aNode.

    PRE: hasChildNode(aNode,aName) == true

    If there is no such node, may return an empty node or raise an exception (?)

    @throws InvalidName if aName is not a valid child name for this node */ AnyNodeRef getAnyChild(NodeRef const& aNode, Name const& aName) const; /// return the local Name of the root node of this tree Name getRootName() const; /// return the local Name of node aNode in this tree Name getName(NodeRef const& aNode) const; /// return the local Name of node aNode in this tree Name getName(AnyNodeRef const& aNode) const; /// return the local Name of value aValue in this tree Name getName(ValueRef const& aValue) const; /// return the Attributes of node aNode in this tree Attributes getAttributes(NodeRef const& aNode) const; /// return the Attributes of node aNode in this tree Attributes getAttributes(AnyNodeRef const& aNode) const; /// return the Attributes of value aValue in this tree Attributes getAttributes(ValueRef const& aValue) const; /// get the Uno Type of value aValue in this tree UnoType getUnoType(ValueRef const& aValue) const; // Parent/NodeRef context handling public: /// return the parent NodeRef of aNode (or an empty node, if it is the tree root) NodeRef getParent(AnyNodeRef const& aNode) const; /// return the parent NodeRef of aNode (or an empty node, if it is the tree root) NodeRef getParent(NodeRef const& aNode) const; /// return the parent NodeRef of aValue (or an empty node, if it is the tree root) NodeRef getParent(ValueRef const& aValue) const; /// return the Path of aNode, relative to the tree root (or an empty path if it is empty) RelativePath getLocalPath(NodeRef const& aNode) const; /// return the Path of aNode RelativePath getLocalPath(ValueRef const& aNode) const; /// gets the root node of this tree NodeRef getRootNode() const; /// checks whether aNode is the root node of this tree bool isRootNode(NodeRef const& aNode) const; public: // value handling /** retrieves the current value for aNode, provided there is one and it is available. */ UnoAny getNodeValue(ValueRef const& aNode) const; // only works for value nodes // default value handling /// ensure default values are available for nodes where they can be provided at all void ensureDefaults() const; /// checks whether aNode assumes its default value bool isNodeDefault(ValueRef const& aNode) const; // only works for value nodes /// checks whether aNode assumes its default state bool isNodeDefault(AnyNodeRef const& aNode) const; /** retrieves the default value for aNode, provided there is one and it is available.

    call Tree::ensureDefaults first to achieve best results

    */ UnoAny getNodeDefault(ValueRef const& aNode) const; // only works for value nodes /** retrieves the default value for aNode, provided there is one and it is available.

    call Tree::ensureDefaults first to achieve best results

    */ UnoAny getNodeDefault(AnyNodeRef const& aNode) const; // Tree context handling public: /// gets the parent tree of this tree, if available Tree getContextTree() const; /// gets the parent node of this tree ('s root node), if available NodeRef getContextNode() const; /// gets the path of the (possibly fictitious) parent node of this tree AbsolutePath getContextPath() const; // Update handling public: /// checks whether there are pending changes on this tree bool hasChanges() const; /// lists any pending changes on this tree bool collectChanges(NodeChanges& aChanges) const; /// applies aChange to aNode within this tree void integrate(NodeChange& aChange, NodeRef const& aNode, bool bLocal) const; /// applies aChange to aNode within this tree void integrate(NodeChange& aChange, ValueRef const& aNode, bool bLocal) const; /// applies aChanges to the children or descendants of aNode within this tree void integrate(NodeChanges& aChanges, NodeRef const& aNode, bool bLocal) const; /// applies aChanges to the descendants of aNode within this tree void integrate(NodeChangesTree& aChanges, NodeRef const& aNode) const; // Visitor handling public: /// dispatch node aNode to a Visitor NodeVisitor::Result visit(NodeRef const& aNode, NodeVisitor& aVisitor) const { return aVisitor.handle(*this,aNode); } /// dispatch node aNode to a Visitor NodeVisitor::Result visit(ValueRef const& aNode, NodeVisitor& aVisitor) const { return aVisitor.handle(*this,aNode); } /// dispatch node aNode to a Visitor NodeVisitor::Result visit(AnyNodeRef const& aNode, NodeVisitor& aVisitor) const; /** lets aVisitor visit the child nodes of aNode

    The order in which nodes are visited is repeatable (but currently unspecified)

    Visits nodes until NodeVisitor::DONE is returned, then returns NodeVisitor::DONE.
    If all visits return NodeVisitor::CONTINUE, returns NodeVisitor::CONTINUE.
    If no children are present, returns NodeVisitor::CONTINUE

    */ NodeVisitor::Result dispatchToChildren(NodeRef const& aNode, NodeVisitor& aVisitor) const; /** lets aVisitor visit the child nodes of aNode

    The order in which nodes are visited is repeatable (but currently unspecified)

    Visits nodes until NodeVisitor::DONE is returned, then returns NodeVisitor::DONE.
    If all visits return NodeVisitor::CONTINUE, returns NodeVisitor::CONTINUE.
    If no children are present, returns NodeVisitor::CONTINUE

    */ NodeVisitor::Result dispatchToChildren(AnyNodeRef const& aNode, NodeVisitor& aVisitor) const; // More NodeRef handling public: NodeRef bind(NodeOffset nNode) const; NodeRef rebind(NodeRef const& aNode) const; // Comparison public: friend bool equalTree(Tree const& lhs, Tree const& rhs) { return lhs.m_pImpl == rhs.m_pImpl; } private: friend class TreeImplHelper; TreeImpl* m_pImpl; }; //------------------------------------------------------------------------- class NodeID { public: NodeID(Tree const& rTree, NodeRef const& rNode); NodeID(TreeImpl* pImpl, NodeOffset nNode); // comparison // equality friend bool operator==(NodeID const& lhs, NodeID const& rhs) { return lhs.m_pTree == rhs.m_pTree && lhs.m_nNode == rhs.m_nNode; } // ordering friend bool operator < (NodeID const& lhs, NodeID const& rhs); // checking bool isEmpty() const; // checking bool isValidNode() const; // hashing size_t hashCode() const; // use as index - returns a value in the range 0..rTree.getContainedNodes() for the tree used to construct this NodeOffset toIndex() const; private: friend class TreeImplHelper; TreeImpl* m_pTree; NodeOffset m_nNode; }; //------------------------------------------------------------------------- /** make a Name out of sName. @throws InvalidName if sName is not a valid name for a aNode within aTree */ Name validateNodeName(OUString const& sName, Tree const& aTree, NodeRef const& aNode ); /** reduce aPath to be a path relative to (aTree,aNode) @returns aPath if it already is a relative path or the part of it relative to aNode if it is an absolute path that to a descendant of aNode @throws InvalidName if aPath is an absolute path that is not to a descendant of aNode */ RelativePath reduceRelativePath(OUString const& aPath, Tree const& aTree, NodeRef const& aBaseNode); /** checks whether there are any immediate children of aNode (which is in aTree) @return if a child node exists otherwise */ bool hasChildOrElement(Tree const& aTree, NodeRef const& aNode); /** checks whether there is an immediate child of aNode (which is in aTree) specified by aName @return if the child node exists otherwise */ bool hasChildOrElement(Tree const& aTree, NodeRef const& aNode, Name const& aName); /** tries to find the immediate child of aNode (which is in aTree) specified by aName

    On return aNode is modified to refer to the node found and aTree will then refer to the tree that node is in.

    @return if the child node exists (so aNode and aTree refer to the desired node), otherwise */ bool findInnerChildNode(Tree& aTree, NodeRef& aNode, Name const& aName); /** tries to find the immediate child of aNode (which is in aTree) specified by aName

    On return aNode is modified to refer to the node found and aTree will then refer to the tree that node is in.

    Caution: May miss an existing child unless the child has been accessed before.

    @return if the child node exists and is available (so aNode and aTree refer to the desired node), otherwise @see NodeRef::getAvailableChild */ bool findInnerAvailableChildNode(Tree& aTree, NodeRef& aNode, Name const& aName); /** tries to find the descendant of aNode (which is in aTree) specified by aPath

    This function follows the given path stepwise, until a requested node is missing in the tree.

    On return aNode is modified to refer to the last node found and aTree will then refer to the tree that node is in.

    Also, aPath is modified to contain the unresolved part of the original path.

    @return if the path could be resolved completely (so aNode and aTree refer to the desired node, aPath is empty)
    otherwise */ bool findInnerDescendantNode(Tree& aTree, NodeRef& aNode, RelativePath& aPath); /** tries to find the descendant of aNode (which is in aTree) specified by aPath

    This function follows the given path stepwise, until a requested node is miss in the tree, or is not availbale in a set node.

    On return aNode is modified to refer to the last node found and aTree will then refer to the tree that node is in.

    Also, aPath is modified to contain the unresolved part of the original path.

    Caution: May miss existing descendants unless the node has been accessed before.

    @return if the path could be resolved completely (so aNode and aTree refer to the desired node, aPath is empty)
    otherwise */ bool findInnerDescendantAvailable(Tree& aTree, NodeRef& aNode, RelativePath& aPath); /// test whether the given node is a structural (inner) node bool isStructuralNode(Tree const& aTree, NodeRef const& aNode); /// test whether the given inner node is a group node bool isGroupNode(Tree const& aTree, NodeRef const& aNode); /// get the value for a node that is a simple value (as tree element) UnoAny getSimpleElementValue(Tree const& aTree, NodeRef const& aNode); /// test whether the given inner node is a set node bool isSetNode(Tree const& aTree, NodeRef const& aNode); ISynchronizedData* getRootLock(Tree const& aTree); typedef std::vector NodeIDList; void getAllContainedNodes(Tree const& aTree, NodeIDList& aList); NodeID findNodeFromIndex(Tree const& aTree, NodeOffset nIndex); //------------------------------------------------------------------------- inline bool NodeRef::isValid() const { OSL_ASSERT( m_pImpl != 0 || m_nPos == 0 ); return m_pImpl != 0; } //------------------------------------------------------------------------- inline bool operator!=(NodeID const& lhs, NodeID const& rhs) { return !(lhs == rhs); } //--------------------------------------------------------------------- inline bool operator>=(NodeID const& lhs, NodeID const& rhs) { return !(lhs < rhs); } //--------------------------------------------------------------------- inline bool operator > (NodeID const& lhs, NodeID const& rhs) { return (rhs < lhs); } inline bool operator<=(NodeID const& lhs, NodeID const& rhs) { return !(rhs < lhs); } //------------------------------------------------------------------------- } } #endif // CONFIGMGR_CONFIGNODE_HXX_