/************************************************************************* * * $RCSfile: noderef.hxx,v $ * * $Revision: 1.11 $ * * last change: $Author: jb $ $Date: 2001-09-28 12:44:15 $ * * 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_ #ifndef CONFIGMGR_API_APITYPES_HXX_ #include "apitypes.hxx" #endif #ifndef CONFIGMGR_CONFIGEXCEPT_HXX_ #include "configexcept.hxx" #endif #ifndef CONFIGMGR_CONFIGPATH_HXX_ #include "configpath.hxx" #endif #ifndef _OSL_DIAGNOSE_H_ #include #endif #ifndef INCLUDED_VECTOR #include #define INCLUDED_VECTOR #endif namespace configmgr { class INode; class ISynchronizedData; namespace configapi { class Factory; } namespace configuration { //------------------------------------------------------------------------- class Name; class AbsolutePath; class RelativePath; namespace Path { class Component; } 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; /// checks whether the node aNode has a element node named aName. bool hasElement(NodeRef const& aNode, Path::Component 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 Path::Component 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 AbsolutePath of aNode AbsolutePath getAbsolutePath(NodeRef const& aNode) const; /// gets the AbsolutePath of the root node of this tree AbsolutePath getRootPath() 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 /// checks whether aNode has a default value bool hasNodeDefault(ValueRef const& aNode) const; // only works for value nodes /// checks whether aNode assumes its default value bool isNodeDefault(ValueRef const& aNode) const; // only works for value nodes /// checks whether aNode has a default state bool hasNodeDefault(NodeRef const& aNode) const; /// checks whether aNode assumes its default state bool isNodeDefault(NodeRef const& aNode) const; /// checks whether aNode has a default state bool hasNodeDefault(AnyNodeRef const& aNode) const; /// checks whether aNode assumes its default state bool isNodeDefault(AnyNodeRef const& aNode) const; /// checks whether the default values are available for the children of aNode (if applicable) bool areValueDefaultsAvailable(NodeRef 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 getNodeDefaultValue(ValueRef const& aNode) const; // only works for value nodes // 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; // 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 member of group aNode within aTree */ Name validateChildName(OUString const& sName, Tree const& aTree, NodeRef const& aNode ); /** make a Name out of sName. @throws InvalidName if sName is not a valid name for an element of set aNode within aTree */ Name validateElementName(OUString const& sName, Tree const& aTree, NodeRef const& aNode ); /** make a Name out of sName. @throws InvalidName if sName is not a valid name for a child of aNode within aTree */ Name validateChildOrElementName(OUString const& sName, Tree const& aTree, NodeRef const& aNode ); /** make one path component out of sName. @throws InvalidName if sName is not a valid name for an element of set aNode within aTree */ Path::Component validateElementPathComponent(OUString const& sName, Tree const& aTree, NodeRef const& aNode ); /** parse aPath into a relative path, valid in the context of node aNode in aTree. @returns aPath parsed as a relative path @throws InvalidName if aPath is not a relative path or not valid in the context of aNode */ RelativePath validateRelativePath(OUString const& aPath, Tree const& aTree, NodeRef const& aNode); /** parse aPath as a configuration path and reduce it to be relative to node aNode in aTree. @returns the result of parsing aPath, if that results in a relative path, or the part of it relative to aNode, if it is an absolute path to a descendant of aNode @throws InvalidName if aPath is not awell-formed path or if it is an absolute path that is not to a descendant of aNode */ RelativePath validateAndReducePath(OUString const& aPath, Tree const& aTree, NodeRef const& aNode); /** 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); /** 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, Path::Component 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 findInnerChildOrAvailableElement(Tree& aTree, NodeRef& aNode, Name const& aName); /// 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_