Version 4.0.0.1, tag libreoffice-4.0.0.1
[LibreOffice.git] / unotools / source / config / configvaluecontainer.cxx
blobfd3ca175df87090094c4d9466c185041edb3835d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <unotools/configvaluecontainer.hxx>
21 #include <unotools/confignode.hxx>
22 #include <tools/debug.hxx>
23 #include <comphelper/stl_types.hxx>
24 #include <uno/data.h>
25 #include <algorithm>
27 #ifdef DBG_UTIL
28 #include <rtl/strbuf.hxx>
29 #endif
31 //.........................................................................
32 namespace utl
34 //.........................................................................
36 using namespace ::com::sun::star::uno;
37 using namespace ::com::sun::star::lang;
39 //=====================================================================
40 //= NodeValueAccessor
41 //=====================================================================
42 enum LocationType
44 ltSimplyObjectInstance,
45 ltAnyInstance,
47 ltUnbound
50 struct NodeValueAccessor
52 private:
53 ::rtl::OUString sRelativePath; // the relative path of the node
54 LocationType eLocationType; // the type of location where the value is stored
55 void* pLocation; // the pointer to the location
56 Type aDataType; // the type object pointed to by pLocation
58 public:
59 NodeValueAccessor( const ::rtl::OUString& _rNodePath );
61 void bind( void* _pLocation, const Type& _rType );
63 bool isBound( ) const { return ( ltUnbound != eLocationType ) && ( NULL != pLocation ); }
64 const ::rtl::OUString& getPath( ) const { return sRelativePath; }
65 LocationType getLocType( ) const { return eLocationType; }
66 void* getLocation( ) const { return pLocation; }
67 const Type& getDataType( ) const { return aDataType; }
69 bool operator == ( const NodeValueAccessor& rhs ) const;
70 bool operator != ( const NodeValueAccessor& rhs ) const { return !operator == ( rhs ); }
73 NodeValueAccessor::NodeValueAccessor( const ::rtl::OUString& _rNodePath )
74 :sRelativePath( _rNodePath )
75 ,eLocationType( ltUnbound )
76 ,pLocation( NULL )
80 bool NodeValueAccessor::operator == ( const NodeValueAccessor& rhs ) const
82 return ( sRelativePath == rhs.sRelativePath )
83 && ( eLocationType == rhs.eLocationType )
84 && ( pLocation == rhs.pLocation );
87 void NodeValueAccessor::bind( void* _pLocation, const Type& _rType )
89 DBG_ASSERT( !isBound(), "NodeValueAccessor::bind: already bound!" );
91 eLocationType = ltSimplyObjectInstance;
92 pLocation = _pLocation;
93 aDataType = _rType;
96 #ifndef UNX
97 static
98 #endif
99 void lcl_copyData( const NodeValueAccessor& _rAccessor, const Any& _rData, ::osl::Mutex& _rMutex )
101 ::osl::MutexGuard aGuard( _rMutex );
103 DBG_ASSERT( _rAccessor.isBound(), "::utl::lcl_copyData: invalid accessor!" );
104 switch ( _rAccessor.getLocType() )
106 case ltSimplyObjectInstance:
108 if ( _rData.hasValue() )
110 #ifdef DBG_UTIL
111 sal_Bool bSuccess =
112 #endif
113 // assign the value
114 uno_type_assignData(
115 _rAccessor.getLocation(), _rAccessor.getDataType().getTypeLibType(),
116 const_cast< void* >( _rData.getValue() ), _rData.getValueType().getTypeLibType(),
117 (uno_QueryInterfaceFunc)cpp_queryInterface, (uno_AcquireFunc)cpp_acquire, (uno_ReleaseFunc)cpp_release
119 #ifdef DBG_UTIL
120 rtl::OStringBuffer aBuf( 256 );
121 aBuf.append("::utl::lcl_copyData( Accessor, Any ): could not assign the data (node path: ");
122 aBuf.append( rtl::OUStringToOString( _rAccessor.getPath(), RTL_TEXTENCODING_ASCII_US ) );
123 aBuf.append( " !" );
124 DBG_ASSERT( bSuccess, aBuf.getStr() );
125 #endif
127 else {
128 DBG_WARNING( "::utl::lcl_copyData: NULL value lost!" );
131 break;
132 case ltAnyInstance:
133 // a simple assignment of an Any ...
134 *static_cast< Any* >( _rAccessor.getLocation() ) = _rData;
135 break;
136 default:
137 break;
141 #ifndef UNX
142 static
143 #endif
144 void lcl_copyData( Any& _rData, const NodeValueAccessor& _rAccessor, ::osl::Mutex& _rMutex )
146 ::osl::MutexGuard aGuard( _rMutex );
148 DBG_ASSERT( _rAccessor.isBound(), "::utl::lcl_copyData: invalid accessor!" );
149 switch ( _rAccessor.getLocType() )
151 case ltSimplyObjectInstance:
152 // a simple setValue ....
153 _rData.setValue( _rAccessor.getLocation(), _rAccessor.getDataType() );
154 break;
156 case ltAnyInstance:
157 // a simple assignment of an Any ...
158 _rData = *static_cast< Any* >( _rAccessor.getLocation() );
159 break;
160 default:
161 break;
165 //=====================================================================
166 //= functors on NodeValueAccessor instances
167 //=====================================================================
169 /// base class for functors syncronizing between exchange locations and config sub nodes
170 struct SubNodeAccess : public ::std::unary_function< NodeValueAccessor, void >
172 protected:
173 const OConfigurationNode& m_rRootNode;
174 ::osl::Mutex& m_rMutex;
176 public:
177 SubNodeAccess( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex )
178 :m_rRootNode( _rRootNode )
179 ,m_rMutex( _rMutex )
184 struct UpdateFromConfig : public SubNodeAccess
186 public:
187 UpdateFromConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { }
189 void operator() ( NodeValueAccessor& _rAccessor )
191 ::utl::lcl_copyData( _rAccessor, m_rRootNode.getNodeValue( _rAccessor.getPath( ) ), m_rMutex );
195 struct UpdateToConfig : public SubNodeAccess
197 public:
198 UpdateToConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { }
200 void operator() ( NodeValueAccessor& _rAccessor )
202 Any aNewValue;
203 lcl_copyData( aNewValue, _rAccessor, m_rMutex );
204 m_rRootNode.setNodeValue( _rAccessor.getPath( ), aNewValue );
208 DECLARE_STL_VECTOR( NodeValueAccessor, NodeValueAccessors );
210 //=====================================================================
211 //= OConfigurationValueContainerImpl
212 //=====================================================================
213 struct OConfigurationValueContainerImpl
215 Reference< XMultiServiceFactory > xORB; // the service factory
216 ::osl::Mutex& rMutex; // the mutex for accessing the data containers
217 OConfigurationTreeRoot aConfigRoot; // the configuration node we're accessing
219 NodeValueAccessors aAccessors; // the accessors to the node values
221 OConfigurationValueContainerImpl( const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rMutex )
222 :xORB( _rxORB )
223 ,rMutex( _rMutex )
228 //=====================================================================
229 //= OConfigurationValueContainer
230 //=====================================================================
232 OConfigurationValueContainer::OConfigurationValueContainer(
233 const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rAccessSafety,
234 const sal_Char* _pConfigLocation, const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels )
235 :m_pImpl( new OConfigurationValueContainerImpl( _rxORB, _rAccessSafety ) )
237 implConstruct( ::rtl::OUString::createFromAscii( _pConfigLocation ), _nAccessFlags, _nLevels );
240 OConfigurationValueContainer::~OConfigurationValueContainer()
242 delete m_pImpl;
245 void OConfigurationValueContainer::implConstruct( const ::rtl::OUString& _rConfigLocation,
246 const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels )
248 DBG_ASSERT( !m_pImpl->aConfigRoot.isValid(), "OConfigurationValueContainer::implConstruct: already initialized!" );
250 // .................................
251 // create the configuration node we're about to work with
252 m_pImpl->aConfigRoot = OConfigurationTreeRoot::createWithServiceFactory(
253 m_pImpl->xORB,
254 _rConfigLocation,
255 _nLevels,
256 ( _nAccessFlags & CVC_UPDATE_ACCESS ) ? OConfigurationTreeRoot::CM_UPDATABLE : OConfigurationTreeRoot::CM_READONLY,
257 ( _nAccessFlags & CVC_IMMEDIATE_UPDATE ) ? sal_False : sal_True
259 #ifdef DBG_UTIL
260 rtl::OStringBuffer aBuf(256);
261 aBuf.append("Could not access the configuration node located at ");
262 aBuf.append( rtl::OUStringToOString( _rConfigLocation, RTL_TEXTENCODING_ASCII_US ) );
263 aBuf.append( " !" );
264 DBG_ASSERT( m_pImpl->aConfigRoot.isValid(), aBuf.getStr() );
265 #endif
268 void OConfigurationValueContainer::registerExchangeLocation( const sal_Char* _pRelativePath,
269 void* _pContainer, const Type& _rValueType )
271 // checks ....
272 DBG_ASSERT( _pContainer, "OConfigurationValueContainer::registerExchangeLocation: invalid container location!" );
273 DBG_ASSERT( ( TypeClass_CHAR == _rValueType.getTypeClass( ) )
274 || ( TypeClass_BOOLEAN == _rValueType.getTypeClass( ) )
275 || ( TypeClass_BYTE == _rValueType.getTypeClass( ) )
276 || ( TypeClass_SHORT == _rValueType.getTypeClass( ) )
277 || ( TypeClass_LONG == _rValueType.getTypeClass( ) )
278 || ( TypeClass_DOUBLE == _rValueType.getTypeClass( ) )
279 || ( TypeClass_STRING == _rValueType.getTypeClass( ) )
280 || ( TypeClass_SEQUENCE == _rValueType.getTypeClass( ) ),
281 "OConfigurationValueContainer::registerExchangeLocation: invalid type!" );
283 // build an accessor for this container
284 NodeValueAccessor aNewAccessor( ::rtl::OUString::createFromAscii( _pRelativePath ) );
285 aNewAccessor.bind( _pContainer, _rValueType );
287 // insert it into our structure
288 implRegisterExchangeLocation( aNewAccessor );
291 void OConfigurationValueContainer::read( )
293 std::for_each(
294 m_pImpl->aAccessors.begin(),
295 m_pImpl->aAccessors.end(),
296 UpdateFromConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex )
300 void OConfigurationValueContainer::write( sal_Bool _bCommit )
302 // collect the current values in the exchange locations
303 std::for_each(
304 m_pImpl->aAccessors.begin(),
305 m_pImpl->aAccessors.end(),
306 UpdateToConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex )
309 // commit the changes done (if requested)
310 if ( _bCommit )
311 commit( sal_False );
314 void OConfigurationValueContainer::commit( sal_Bool _bWrite )
316 // write the current values in the exchange locations (if requested)
317 if ( _bWrite )
318 write( sal_False );
320 // commit the changes done
321 m_pImpl->aConfigRoot.commit( );
324 void OConfigurationValueContainer::implRegisterExchangeLocation( const NodeValueAccessor& _rAccessor )
326 // some checks
327 DBG_ASSERT( !m_pImpl->aConfigRoot.isValid() || m_pImpl->aConfigRoot.hasByHierarchicalName( _rAccessor.getPath() ),
328 "OConfigurationValueContainer::implRegisterExchangeLocation: invalid relative path!" );
330 #ifdef DBG_UTIL
331 // another check (should be the first container for this node)
332 ConstNodeValueAccessorsIterator aExistent = ::std::find(
333 m_pImpl->aAccessors.begin(),
334 m_pImpl->aAccessors.end(),
335 _rAccessor
337 DBG_ASSERT( m_pImpl->aAccessors.end() == aExistent, "OConfigurationValueContainer::implRegisterExchangeLocation: already registered a container for this subnode!" );
338 #endif
340 // remember the accessor
341 m_pImpl->aAccessors.push_back( _rAccessor );
343 // and initially fill the value
344 lcl_copyData( _rAccessor, m_pImpl->aConfigRoot.getNodeValue( _rAccessor.getPath() ), m_pImpl->rMutex );
347 //.........................................................................
348 } // namespace utl
349 //.........................................................................
351 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */