/************************************************************************* * * $RCSfile: noderef.hxx,v $ * * $Revision: 1.8 $ * * last change: $Author: jb $ $Date: 2001-02-13 16:13: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_ #ifndef _OSL_DIAGNOSE_H_ #include #endif #include "apitypes.hxx" #include "configexcept.hxx" #include namespace configmgr { class INode; class ISynchronizedData; namespace configapi { class Factory; } namespace configuration { //------------------------------------------------------------------------- class Name; class AbsolutePath; class RelativePath; struct NodeInfo; 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; //------------------------------------------------------------------------- struct NodeState { enum State { eDEFAULT, eREPLACING, eMODIFYING, eREMOVING, eUNCHANGED = -1 }; }; //------------------------------------------------------------------------- class NodeID; class NodeRef; 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. 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(NodeRef const& aNode) = 0; }; //------------------------------------------------------------------------- /// represents a 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; /// checks whether this node has any child nodes (of its own). bool hasChildren() const; /// checks whether this node owns a child node named aName. bool hasChild(Name const& aName) const; /** gets the owned child node named aName of this node.

Also sets aTree to point to the tree containing that node.

PRE: hasChild(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 getChild(Name const& aName, Tree& aTree) const; /** gets the owned child node named aName of this node, if it is available.

Also sets aTree to point to the tree containing that node.

If there is no such node, returns an empty node.

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 */ NodeRef getAvailableChild(Name const& aName, Tree& aTree) const; /// return a NodeInfo showing the attributes of this NodeInfo getInfo() const; /// return a NodeInfo showing the attributes of this Attributes getAttributes() const; /// return the local Name of this (or an empty name, if there isn't one) Name getName() const; /// get the Uno Type of the object represented by this node UnoType getUnoType() const; /// dispatch this node to a Visitor NodeVisitor::Result accept(NodeVisitor& aVisitor) const { return aVisitor.handle(*this); } private: friend class Tree; friend class TreeImplHelper; 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)

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 nodes NodeOffset getContainedNodeCount() const; /// checks whether the node aNode is a valid node in this tree. bool isValidNode(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 have a child node (in this tree) named aName. bool hasChild(NodeRef const& aNode, Name const& aName) const; /** gets the child node (in this tree) named aName of node aNode.

    PRE: hasChild(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 getChild(NodeRef const& aNode, Name const& aName) const; // Parent/NodeRef context handling public: /// return the parent NodeRef of aNode (or an empty node, if it is the tree root) NodeRef getParent(NodeRef const& aNode) 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; /// 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; // default value handling public: /// 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(NodeRef 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(NodeRef 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; /// 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 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: /** 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; // 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); /* * 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 @returns an empty path, 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, argument::NoValidate); */ /** checks whether there are any immediate children of aNode (which is in aTree) @return if a child node exists otherwise */ bool hasChildNode(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 hasChildNode(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 findChildNode(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 findAvailableChildNode(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 findDescendantNode(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 findDescendantAvailable(Tree& aTree, NodeRef& aNode, RelativePath& aPath); /// test whether the given node is a plain value bool isSimpleValue(Tree const& aTree, NodeRef const& aNode); /// test whether the given node is a inner group node bool isGroupNode(Tree const& aTree, NodeRef const& aNode); /// test whether the given node is a inner set node bool isSetNode(Tree const& aTree, NodeRef const& aNode); /** extract the value from a plain value

    PRE: isSimpleValue(aTree,aNode)

    */ UnoAny getSimpleValue(Tree const& aTree, NodeRef const& aNode); ISynchronizedData* getRootLock(Tree const& aTree); typedef std::vector NodeIDList; void getAllContainedNodes(Tree const& aTree, NodeIDList& aList); void getAllChildrenHelper(NodeID const& aNode, NodeIDList& aList); NodeID getParentHelper(NodeID const& aNode); NodeID findNeighbor(NodeID const& aNode, NodeOffset nIndex); NodeID findNodeFromIndex(NodeID const& aNode, 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_