xref: /trunk/main/unotools/inc/unotools/confignode.hxx (revision 152e651ef53ab2fae14bf93407606b2c7fcbd35b)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 #ifndef _UNOTOOLS_CONFIGNODE_HXX_
24 #define _UNOTOOLS_CONFIGNODE_HXX_
25 
26 #include "unotools/unotoolsdllapi.h"
27 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
28 #include <com/sun/star/container/XNameAccess.hpp>
29 #include <com/sun/star/container/XNameContainer.hpp>
30 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 #include <com/sun/star/util/XChangesBatch.hpp>
32 #include <unotools/eventlisteneradapter.hxx>
33 
34 namespace comphelper
35 {
36     class ComponentContext;
37 }
38 
39 //........................................................................
40 namespace utl
41 {
42 //........................................................................
43 
44     //========================================================================
45     //= OConfigurationNode
46     //========================================================================
47     class OConfigurationTreeRoot;
48     /** a small wrapper around a configuration node.<p/>
49         Nodes in the terminology used herein are <em>inner</em> nodes of a configuration
50         tree, which means <em>no leafs</em>.
51     */
52     class UNOTOOLS_DLLPUBLIC OConfigurationNode : public ::utl::OEventListenerAdapter
53     {
54     private:
55         ::com::sun::star::uno::Reference< ::com::sun::star::container::XHierarchicalNameAccess >
56                     m_xHierarchyAccess;     /// accessing children grandchildren (mandatory interface of our UNO object)
57         ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >
58                     m_xDirectAccess;        /// accessing children  (mandatory interface of our UNO object)
59         ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace >
60                     m_xReplaceAccess;       /// replacing child values
61         ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >
62                     m_xContainerAccess;     /// modifying set nodes  (optional interface of our UNO object)
63         ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >
64                     m_xDummy;
65         sal_Bool    m_bEscapeNames;         /// escape names before accessing children ?
66 
67         ::rtl::OUString
68                     m_sCompletePath;
69 
70         OConfigurationNode  insertNode(const ::rtl::OUString& _rName,const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xNode) const throw();
71 
72     protected:
73         /// constructs a node object with an interface representing a node
74         OConfigurationNode(
75             const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxNode
76         );
77 
78         const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >&
getUNONode() const79             getUNONode() const { return m_xDirectAccess; }
80 
81     public:
82         /// constructs an empty and invalid node object
OConfigurationNode()83         OConfigurationNode() :m_bEscapeNames(sal_False) { }
84         /// copy ctor
85         OConfigurationNode(const OConfigurationNode& _rSource);
86 
87         /// assignment
88         const OConfigurationNode& operator=(const OConfigurationNode& _rSource);
89 
90         /// dtor
~OConfigurationNode()91         ~OConfigurationNode() {}
92 
93         /// returns the local name of the node
94         ::rtl::OUString     getLocalName() const;
95 
96         /// returns the fully qualified path of the node
97         ::rtl::OUString     getNodePath() const;
98 
99         /** open a sub node
100             @param      _rPath      access path of the to-be-opened sub node. May be a hierarchical path.
101         */
102         OConfigurationNode  openNode(const ::rtl::OUString& _rPath) const throw();
103 
openNode(const sal_Char * _pAsciiPath) const104         OConfigurationNode  openNode( const sal_Char* _pAsciiPath ) const
105         {
106             return openNode( ::rtl::OUString::createFromAscii( _pAsciiPath ) );
107         }
108 
109         /** create a new child node
110 
111             If the object represents a set node, this method may be used to create a new child. For non-set-nodes, the
112             method will fail.<br/>
113             Unless the respective operations on the pure configuration API, the to-be-created node immediately
114             becomes a part of it's hierarchy, no explicit insertion is necessary.
115             @param      _rName      name for the new child. Must be level-1-depth.
116         */
117         OConfigurationNode  createNode(const ::rtl::OUString& _rName) const throw();
118 
createNode(const sal_Char * _pAsciiName) const119         OConfigurationNode  createNode( const sal_Char* _pAsciiName ) const
120         {
121             return createNode( ::rtl::OUString::createFromAscii( _pAsciiName ) );
122         }
123 
124         /** appends a node under a new name
125 
126             If the object represents a set node, this method may be used to create a new child. For non-set-nodes, the
127             method will fail.<br/>
128             Unless the respective operations on the pure configuration API, the to-be-created node immediately
129             becomes a part of it's hierarchy, no explicit insertion is necessary.
130             @param      _rName      name for the new child. Must be level-1-depth.
131             @param      _aNewNode   the node which should be appended
132         */
133         OConfigurationNode  appendNode(const ::rtl::OUString& _rName,const OConfigurationNode& _aNewNode) const throw();
134 
appendNode(const sal_Char * _pAsciiName,const OConfigurationNode & _aNewNode) const135         OConfigurationNode  appendNode( const sal_Char* _pAsciiName, const OConfigurationNode& _aNewNode ) const
136         {
137             return appendNode( ::rtl::OUString::createFromAscii( _pAsciiName ), _aNewNode );
138         }
139 
140         /** remove an existent child nod
141 
142             If the object represents a set node, this method may be used to delete an existent child. For non-set-nodes,
143             the method will fail.
144         */
145         sal_Bool            removeNode(const ::rtl::OUString& _rName) const throw();
146 
removeNode(const sal_Char * _pAsciiName) const147         sal_Bool            removeNode( const sal_Char* _pAsciiName ) const
148         {
149             return removeNode( ::rtl::OUString::createFromAscii( _pAsciiName ) );
150         }
151 
152         /** retrieves the content of a descendant
153 
154             the returned value may contain anything from an interface (if <arg>_rPath</arg> refers to inner node of
155             the configuration tree) to any explicit value (e.g. string, integer) or even void.<br/>
156             Unfortunately, this implies that if a void value is returned, you won't have a clue if this means
157             "the path does not exist" (besides the assertion made :), or if the value is really void.
158         */
159         ::com::sun::star::uno::Any
160                             getNodeValue(const ::rtl::OUString& _rPath) const throw();
161 
162         ::com::sun::star::uno::Any
getNodeValue(const sal_Char * _pAsciiPath) const163                             getNodeValue( const sal_Char* _pAsciiPath ) const
164         {
165             return getNodeValue( ::rtl::OUString::createFromAscii( _pAsciiPath ) );
166         }
167 
168         /** write a node value<p/>
169             The value given is written into the node specified by the given relative path.<br/>
170             In opposite to <method>getNodeValue</method>, _rName must refer to a leaf in the configuration tree, not an inner
171             node.
172             @return     sal_True if and only if the write was successful.
173         */
174         sal_Bool            setNodeValue(const ::rtl::OUString& _rPath, const ::com::sun::star::uno::Any& _rValue) const throw();
175 
setNodeValue(const sal_Char * _pAsciiPath,const::com::sun::star::uno::Any & _rValue) const176         sal_Bool            setNodeValue( const sal_Char* _pAsciiPath, const ::com::sun::star::uno::Any& _rValue ) const
177         {
178             return setNodeValue( ::rtl::OUString::createFromAscii( _pAsciiPath ), _rValue );
179         }
180 
181         /// return the names of the existing children
182         ::com::sun::star::uno::Sequence< ::rtl::OUString >
183                             getNodeNames() const throw();
184 
185         /** enables or disables name escaping when accessing direct children<p/>
186             Escaping is disabled by default, usually you enable it for set nodes (e.g. with calling setEscape(isSetNode)).
187             Once escaping is enabled, you should not access indirect children (e.g. openNode("child/grandchild"), 'cause
188             escaping for such names may not be supported by the underlying API objects.
189             @see getEscape
190         */
191         void        setEscape(sal_Bool _bEnable = sal_True);
192         /** get the flag specifying the current escape behaviour
193             @see setEscape
194         */
getEscape() const195         sal_Bool    getEscape() const { return m_bEscapeNames; }
196 
197         /// invalidate the object
198         virtual void clear() throw();
199 
200         // -----------------------
201         // meta informations about the node
202 
203         /// checks whether or not the object represents a set node.
204         sal_Bool isSetNode() const;
205 
206         /// checks whether or not a direct child with a given name exists
207         sal_Bool hasByName(const ::rtl::OUString& _rName) const throw();
hasByName(const sal_Char * _pAsciiName) const208         sal_Bool hasByName( const sal_Char* _pAsciiName ) const { return hasByName( ::rtl::OUString::createFromAscii( _pAsciiName ) ); }
209 
210         /// checks whether or not a descendent (no matter if direct or indirect) with the given name exists
211         sal_Bool hasByHierarchicalName( const ::rtl::OUString& _rName ) const throw();
hasByHierarchicalName(const sal_Char * _pAsciiName) const212         sal_Bool hasByHierarchicalName( const sal_Char* _pAsciiName ) const { return hasByHierarchicalName( ::rtl::OUString::createFromAscii( _pAsciiName ) ); }
213 
214         /// check if the objects represents a valid configuration node
isValid() const215         sal_Bool isValid() const { return m_xHierarchyAccess.is(); }
216 
217         /// check whether the object is read-only of updatable
isReadonly() const218         sal_Bool isReadonly() const { return !m_xReplaceAccess.is(); }
219 
220     protected:
221         // OEventListenerAdapter
222         virtual void _disposing( const ::com::sun::star::lang::EventObject& _rSource );
223 
224     protected:
225         enum NAMEORIGIN
226         {
227             NO_CONFIGURATION,       /// the name came from a configuration node
228             NO_CALLER               /// the name came from a client of this class
229         };
230         ::rtl::OUString normalizeName(const ::rtl::OUString& _rName, NAMEORIGIN _eOrigin) const;
231     };
232 
233     //========================================================================
234     //= OConfigurationTreeRoot
235     //========================================================================
236     /** a specialized version of a OConfigurationNode, representing the root
237         of a configuration sub tree<p/>
238         Only this class is able to commit any changes made any any OConfigurationNode
239         objects.
240     */
241     class UNOTOOLS_DLLPUBLIC OConfigurationTreeRoot : public OConfigurationNode
242     {
243         ::com::sun::star::uno::Reference< ::com::sun::star::util::XChangesBatch >
244                                 m_xCommitter;
245     protected:
246         /** ctor<p/>
247         */
248         OConfigurationTreeRoot(
249             const ::com::sun::star::uno::Reference< ::com::sun::star::util::XChangesBatch >& _rxRootNode
250         );
251 
252         /** ctor for a readonly node
253         */
254         OConfigurationTreeRoot(
255             const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxRootNode
256         );
257 
258     public:
259         /// modes to use when creating a top-level node object
260         enum CREATION_MODE
261         {
262             /// open the node (i.e. sub tree) for read access only
263             CM_READONLY,
264             /// open the node (i.e. sub tree) for read and write access, fall back to read-only if write access is not possible
265             CM_UPDATABLE
266         };
267 
268     public:
269         /** default ctor<p/>
270             The object constructed here is invalid (i.e. <method>isValid</method> will return sal_False).
271         */
OConfigurationTreeRoot()272         OConfigurationTreeRoot() :OConfigurationNode() { }
273 
274         /** creates a configuration tree for the given path in the given mode
275         */
276         OConfigurationTreeRoot(
277             const ::comphelper::ComponentContext& i_rContext,
278             const sal_Char* i_pAsciiNodePath,
279             const bool i_bUpdatable
280         );
281 
282         /** creates a configuration tree for the given path in the given mode
283         */
284         OConfigurationTreeRoot(
285             const ::comphelper::ComponentContext& i_rContext,
286             const ::rtl::OUString& i_rNodePath,
287             const bool i_bUpdatable
288         );
289 
290         /// copy ctor
OConfigurationTreeRoot(const OConfigurationTreeRoot & _rSource)291         OConfigurationTreeRoot(const OConfigurationTreeRoot& _rSource)
292             :OConfigurationNode(_rSource), m_xCommitter(_rSource.m_xCommitter) { }
293 
294         /** open a new top-level configuration node
295 
296             opens a new node which is the root if an own configuration sub tree. This is what "top level" means: The
297             node does not have a parent. It does not mean that the node represents a module tree (like org.openoffice.Office.Writer
298             or such).<br/>
299             In opposite to <method>createWithServiceFactory</method>, createWithProvider expects a configuration provider
300             to work with.
301 
302             @param      _rxConfProvider configuration provider to use when retrieving the node.
303             @param      _rPath          path to the node the object should represent
304             @param      _nDepth         depth for node retrieval
305             @param      _eMode          specifies which privileges should be applied when retrieving the node
306 
307             @see    createWithServiceFactory
308         */
309         static OConfigurationTreeRoot createWithProvider(
310                 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxConfProvider,
311                 const ::rtl::OUString& _rPath,
312                 sal_Int32 _nDepth = -1,
313                 CREATION_MODE _eMode = CM_UPDATABLE,
314                 sal_Bool _bLazyWrite = sal_True
315             );
316 
317         /** open a new top-level configuration node<p/>
318             opens a new node which is the root if an own configuration sub tree. This is what "top level" means: The
319             node does not have a parent. It does not mean that the node represents a module tree (like org.openoffice.Office.Writer
320             or such).<br/>
321             In opposite to <method>createWithProvider</method>, createWithProvider expects a service factory. This factory
322             is used to create a configuration provider, and this provider is used to retrieve the node
323             @see    createWithProvider
324             @param      _rxORB          service factory to use to create the configuration provider.
325             @param      _rPath          path to the node the object should represent
326             @param      _nDepth         depth for node retrieval
327             @param      _eMode          specifies which privileges should be applied when retrieving the node
328         */
329         static OConfigurationTreeRoot createWithServiceFactory(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
330             const ::rtl::OUString& _rPath, sal_Int32 _nDepth = -1, CREATION_MODE _eMode = CM_UPDATABLE, sal_Bool _bLazyWrite = sal_True);
331 
332         /** tolerant version of the <member>createWithServiceFactory</member>
333 
334             <p>No assertions are thrown in case of an failure to initialize the configuration service, but once
335             the configuration could be initialized, errors in the creation of the specific node (e.g. because the
336             given node path does not exist) are still asserted.</p>
337         */
338         static OConfigurationTreeRoot tryCreateWithServiceFactory( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
339             const ::rtl::OUString& _rPath, sal_Int32 _nDepth = -1, CREATION_MODE _eMode = CM_UPDATABLE, sal_Bool _bLazyWrite = sal_True );
340 
341         /** commit all changes made on the subtree the object is the root for<p/>
342             All changes made on any <type>OConfigurationNode</type> object retrieved (maybe indirect) from this root
343             object are committed when calling this method.
344             @return     sal_True if and only if the commit was successful
345         */
346         sal_Bool commit() const throw();
347 
348         /// invalidate the object
349         virtual void clear() throw();
350     };
351 
352 //........................................................................
353 }   // namespace utl
354 //........................................................................
355 
356 #endif // _UNOTOOLS_CONFIGNODE_HXX_
357