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 /// assigment 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 358