merge the formfield patch from ooo-build
[ooovba.git] / unotools / source / config / configvaluecontainer.cxx
blobde5be9ed5a305e6e226820d8b03289430d70237c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: configvaluecontainer.cxx,v $
10 * $Revision: 1.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_unotools.hxx"
33 #include <unotools/configvaluecontainer.hxx>
34 #include <unotools/confignode.hxx>
35 #include <tools/debug.hxx>
36 #include <comphelper/stl_types.hxx>
37 #include <uno/data.h>
38 #include <algorithm>
40 #ifdef DBG_UTIL
41 #include <rtl/strbuf.hxx>
42 #endif
44 //.........................................................................
45 namespace utl
47 //.........................................................................
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::lang;
52 //=====================================================================
53 //= NodeValueAccessor
54 //=====================================================================
55 enum LocationType
57 ltSimplyObjectInstance,
58 ltAnyInstance,
60 ltUnbound
63 struct NodeValueAccessor
65 private:
66 ::rtl::OUString sRelativePath; // the relative path of the node
67 LocationType eLocationType; // the type of location where the value is stored
68 void* pLocation; // the pointer to the location
69 Type aDataType; // the type object pointed to by pLocation
71 public:
72 NodeValueAccessor( const ::rtl::OUString& _rNodePath );
74 void bind( void* _pLocation, const Type& _rType );
75 void bind( Any* _pLocation );
77 bool isBound( ) const { return ( ltUnbound != eLocationType ) && ( NULL != pLocation ); }
78 const ::rtl::OUString& getPath( ) const { return sRelativePath; }
79 LocationType getLocType( ) const { return eLocationType; }
80 void* getLocation( ) const { return pLocation; }
81 const Type& getDataType( ) const { return aDataType; }
83 bool operator == ( const NodeValueAccessor& rhs ) const;
84 bool operator != ( const NodeValueAccessor& rhs ) const { return !operator == ( rhs ); }
87 //---------------------------------------------------------------------
88 //--- 20.08.01 17:21:13 -----------------------------------------------
90 NodeValueAccessor::NodeValueAccessor( const ::rtl::OUString& _rNodePath )
91 :sRelativePath( _rNodePath )
92 ,eLocationType( ltUnbound )
93 ,pLocation( NULL )
97 //---------------------------------------------------------------------
98 //--- 20.08.01 17:06:36 -----------------------------------------------
100 bool NodeValueAccessor::operator == ( const NodeValueAccessor& rhs ) const
102 return ( sRelativePath == rhs.sRelativePath )
103 && ( eLocationType == rhs.eLocationType )
104 && ( pLocation == rhs.pLocation );
107 //---------------------------------------------------------------------
108 //--- 20.08.01 17:47:43 -----------------------------------------------
110 void NodeValueAccessor::bind( void* _pLocation, const Type& _rType )
112 DBG_ASSERT( !isBound(), "NodeValueAccessor::bind: already bound!" );
114 eLocationType = ltSimplyObjectInstance;
115 pLocation = _pLocation;
116 aDataType = _rType;
119 //---------------------------------------------------------------------
120 //--- 20.08.01 17:48:47 -----------------------------------------------
122 void NodeValueAccessor::bind( Any* _pLocation )
124 DBG_ASSERT( !isBound(), "NodeValueAccessor::bind: already bound!" );
126 eLocationType = ltAnyInstance;
127 pLocation = _pLocation;
128 aDataType = ::getCppuType( _pLocation );
131 //---------------------------------------------------------------------
132 //--- 20.08.01 17:42:17 -----------------------------------------------
134 #ifndef UNX
135 static
136 #endif
137 void lcl_copyData( const NodeValueAccessor& _rAccessor, const Any& _rData, ::osl::Mutex& _rMutex )
139 ::osl::MutexGuard aGuard( _rMutex );
141 DBG_ASSERT( _rAccessor.isBound(), "::utl::lcl_copyData: invalid accessor!" );
142 switch ( _rAccessor.getLocType() )
144 case ltSimplyObjectInstance:
146 if ( _rData.hasValue() )
148 #ifdef DBG_UTIL
149 sal_Bool bSuccess =
150 #endif
151 // assign the value
152 uno_type_assignData(
153 _rAccessor.getLocation(), _rAccessor.getDataType().getTypeLibType(),
154 const_cast< void* >( _rData.getValue() ), _rData.getValueType().getTypeLibType(),
155 (uno_QueryInterfaceFunc)cpp_queryInterface, (uno_AcquireFunc)cpp_acquire, (uno_ReleaseFunc)cpp_release
157 #ifdef DBG_UTIL
158 rtl::OStringBuffer aBuf( 256 );
159 aBuf.append("::utl::lcl_copyData( Accessor, Any ): could not assign the data (node path: ");
160 aBuf.append( rtl::OUStringToOString( _rAccessor.getPath(), RTL_TEXTENCODING_ASCII_US ) );
161 aBuf.append( " !" );
162 DBG_ASSERT( bSuccess, aBuf.getStr() );
163 #endif
165 else {
166 DBG_WARNING( "::utl::lcl_copyData: NULL value lost!" );
169 break;
170 case ltAnyInstance:
171 // a simple assignment of an Any ...
172 *static_cast< Any* >( _rAccessor.getLocation() ) = _rData;
173 break;
174 default:
175 break;
179 //---------------------------------------------------------------------
180 //--- 21.08.01 12:06:43 -----------------------------------------------
182 #ifndef UNX
183 static
184 #endif
185 void lcl_copyData( Any& _rData, const NodeValueAccessor& _rAccessor, ::osl::Mutex& _rMutex )
187 ::osl::MutexGuard aGuard( _rMutex );
189 DBG_ASSERT( _rAccessor.isBound(), "::utl::lcl_copyData: invalid accessor!" );
190 switch ( _rAccessor.getLocType() )
192 case ltSimplyObjectInstance:
193 // a simple setValue ....
194 _rData.setValue( _rAccessor.getLocation(), _rAccessor.getDataType() );
195 break;
197 case ltAnyInstance:
198 // a simple assignment of an Any ...
199 _rData = *static_cast< Any* >( _rAccessor.getLocation() );
200 break;
201 default:
202 break;
206 //=====================================================================
207 //= functors on NodeValueAccessor instances
208 //=====================================================================
210 //---------------------------------------------------------------------
211 //--- 21.08.01 12:01:16 -----------------------------------------------
213 /// base class for functors syncronizing between exchange locations and config sub nodes
214 struct SubNodeAccess : public ::std::unary_function< NodeValueAccessor, void >
216 protected:
217 const OConfigurationNode& m_rRootNode;
218 ::osl::Mutex& m_rMutex;
220 public:
221 SubNodeAccess( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex )
222 :m_rRootNode( _rRootNode )
223 ,m_rMutex( _rMutex )
228 //---------------------------------------------------------------------
229 //--- 21.08.01 11:25:56 -----------------------------------------------
231 struct UpdateFromConfig : public SubNodeAccess
233 public:
234 UpdateFromConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { }
236 void operator() ( NodeValueAccessor& _rAccessor )
238 ::utl::lcl_copyData( _rAccessor, m_rRootNode.getNodeValue( _rAccessor.getPath( ) ), m_rMutex );
242 //---------------------------------------------------------------------
243 //--- 21.08.01 11:25:56 -----------------------------------------------
245 struct UpdateToConfig : public SubNodeAccess
247 public:
248 UpdateToConfig( const OConfigurationNode& _rRootNode, ::osl::Mutex& _rMutex ) : SubNodeAccess( _rRootNode, _rMutex ) { }
250 void operator() ( NodeValueAccessor& _rAccessor )
252 Any aNewValue;
253 lcl_copyData( aNewValue, _rAccessor, m_rMutex );
254 m_rRootNode.setNodeValue( _rAccessor.getPath( ), aNewValue );
258 //---------------------------------------------------------------------
259 //--- 20.08.01 16:58:24 -----------------------------------------------
261 DECLARE_STL_VECTOR( NodeValueAccessor, NodeValueAccessors );
263 //=====================================================================
264 //= OConfigurationValueContainerImpl
265 //=====================================================================
266 struct OConfigurationValueContainerImpl
268 Reference< XMultiServiceFactory > xORB; // the service factory
269 ::osl::Mutex& rMutex; // the mutex for accessing the data containers
270 OConfigurationTreeRoot aConfigRoot; // the configuration node we're accessing
272 NodeValueAccessors aAccessors; // the accessors to the node values
274 OConfigurationValueContainerImpl( const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rMutex )
275 :xORB( _rxORB )
276 ,rMutex( _rMutex )
281 //=====================================================================
282 //= OConfigurationValueContainer
283 //=====================================================================
285 //---------------------------------------------------------------------
286 //--- 20.08.01 15:53:35 -----------------------------------------------
288 OConfigurationValueContainer::OConfigurationValueContainer(
289 const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rAccessSafety,
290 const sal_Char* _pConfigLocation, const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels )
291 :m_pImpl( new OConfigurationValueContainerImpl( _rxORB, _rAccessSafety ) )
293 implConstruct( ::rtl::OUString::createFromAscii( _pConfigLocation ), _nAccessFlags, _nLevels );
296 //---------------------------------------------------------------------
297 //--- 20.08.01 15:55:20 -----------------------------------------------
299 OConfigurationValueContainer::OConfigurationValueContainer(
300 const Reference< XMultiServiceFactory >& _rxORB, ::osl::Mutex& _rAccessSafety,
301 const ::rtl::OUString& _rConfigLocation, const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels )
302 :m_pImpl( new OConfigurationValueContainerImpl( _rxORB, _rAccessSafety ) )
304 implConstruct( _rConfigLocation, _nAccessFlags, _nLevels );
307 //---------------------------------------------------------------------
308 //--- 20.08.01 16:01:29 -----------------------------------------------
310 OConfigurationValueContainer::~OConfigurationValueContainer()
312 delete m_pImpl;
315 //---------------------------------------------------------------------
316 //--- 20.08.01 15:59:13 -----------------------------------------------
318 const Reference< XMultiServiceFactory >& OConfigurationValueContainer::getServiceFactory( ) const
320 return m_pImpl->xORB;
323 //---------------------------------------------------------------------
324 //--- 20.08.01 16:02:07 -----------------------------------------------
326 void OConfigurationValueContainer::implConstruct( const ::rtl::OUString& _rConfigLocation,
327 const sal_uInt16 _nAccessFlags, const sal_Int32 _nLevels )
329 DBG_ASSERT( !m_pImpl->aConfigRoot.isValid(), "OConfigurationValueContainer::implConstruct: already initialized!" );
331 // .................................
332 // create the configuration node we're about to work with
333 m_pImpl->aConfigRoot = OConfigurationTreeRoot::createWithServiceFactory(
334 m_pImpl->xORB,
335 _rConfigLocation,
336 _nLevels,
337 ( _nAccessFlags & CVC_UPDATE_ACCESS ) ? OConfigurationTreeRoot::CM_PREFER_UPDATABLE : OConfigurationTreeRoot::CM_READONLY,
338 ( _nAccessFlags & CVC_IMMEDIATE_UPDATE ) ? sal_False : sal_True
340 #ifdef DBG_UTIL
341 rtl::OStringBuffer aBuf(256);
342 aBuf.append("Could not access the configuration node located at ");
343 aBuf.append( rtl::OUStringToOString( _rConfigLocation, RTL_TEXTENCODING_ASCII_US ) );
344 aBuf.append( " !" );
345 DBG_ASSERT( m_pImpl->aConfigRoot.isValid(), aBuf.getStr() );
346 #endif
349 //---------------------------------------------------------------------
350 //--- 20.08.01 16:39:05 -----------------------------------------------
352 void OConfigurationValueContainer::registerExchangeLocation( const sal_Char* _pRelativePath,
353 void* _pContainer, const Type& _rValueType )
355 // checks ....
356 DBG_ASSERT( _pContainer, "OConfigurationValueContainer::registerExchangeLocation: invalid container location!" );
357 DBG_ASSERT( ( TypeClass_CHAR == _rValueType.getTypeClass( ) )
358 || ( TypeClass_BOOLEAN == _rValueType.getTypeClass( ) )
359 || ( TypeClass_BYTE == _rValueType.getTypeClass( ) )
360 || ( TypeClass_SHORT == _rValueType.getTypeClass( ) )
361 || ( TypeClass_LONG == _rValueType.getTypeClass( ) )
362 || ( TypeClass_DOUBLE == _rValueType.getTypeClass( ) )
363 || ( TypeClass_STRING == _rValueType.getTypeClass( ) )
364 || ( TypeClass_SEQUENCE == _rValueType.getTypeClass( ) ),
365 "OConfigurationValueContainer::registerExchangeLocation: invalid type!" );
367 // build an accessor for this container
368 NodeValueAccessor aNewAccessor( ::rtl::OUString::createFromAscii( _pRelativePath ) );
369 aNewAccessor.bind( _pContainer, _rValueType );
371 // insert it into our structure
372 implRegisterExchangeLocation( aNewAccessor );
375 //---------------------------------------------------------------------
376 //--- 21.08.01 14:44:45 -----------------------------------------------
378 void OConfigurationValueContainer::registerNullValueExchangeLocation( const sal_Char* _pRelativePath, Any* _pContainer )
380 // build an accessor for this container
381 NodeValueAccessor aNewAccessor( ::rtl::OUString::createFromAscii( _pRelativePath ) );
382 aNewAccessor.bind( _pContainer );
384 // insert it into our structure
385 implRegisterExchangeLocation( aNewAccessor );
388 //---------------------------------------------------------------------
389 //--- 21.08.01 10:23:34 -----------------------------------------------
391 void OConfigurationValueContainer::read( )
393 for_each(
394 m_pImpl->aAccessors.begin(),
395 m_pImpl->aAccessors.end(),
396 UpdateFromConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex )
400 //---------------------------------------------------------------------
401 //--- 21.08.01 12:04:48 -----------------------------------------------
403 void OConfigurationValueContainer::write( sal_Bool _bCommit )
405 // collect the current values in the exchange locations
406 for_each(
407 m_pImpl->aAccessors.begin(),
408 m_pImpl->aAccessors.end(),
409 UpdateToConfig( m_pImpl->aConfigRoot, m_pImpl->rMutex )
412 // commit the changes done (if requested)
413 if ( _bCommit )
414 commit( sal_False );
417 //---------------------------------------------------------------------
418 //--- 21.08.01 12:09:45 -----------------------------------------------
420 void OConfigurationValueContainer::commit( sal_Bool _bWrite )
422 // write the current values in the exchange locations (if requested)
423 if ( _bWrite )
424 write( sal_False );
426 // commit the changes done
427 m_pImpl->aConfigRoot.commit( );
430 //---------------------------------------------------------------------
431 //--- 20.08.01 17:29:27 -----------------------------------------------
433 void OConfigurationValueContainer::implRegisterExchangeLocation( const NodeValueAccessor& _rAccessor )
435 // some checks
436 DBG_ASSERT( !m_pImpl->aConfigRoot.isValid() || m_pImpl->aConfigRoot.hasByHierarchicalName( _rAccessor.getPath() ),
437 "OConfigurationValueContainer::implRegisterExchangeLocation: invalid relative path!" );
439 #ifdef DBG_UTIL
440 // another check (should be the first container for this node)
441 ConstNodeValueAccessorsIterator aExistent = ::std::find(
442 m_pImpl->aAccessors.begin(),
443 m_pImpl->aAccessors.end(),
444 _rAccessor
446 DBG_ASSERT( m_pImpl->aAccessors.end() == aExistent, "OConfigurationValueContainer::implRegisterExchangeLocation: already registered a container for this subnode!" );
447 #endif
449 // remember the accessor
450 m_pImpl->aAccessors.push_back( _rAccessor );
452 // and initially fill the value
453 lcl_copyData( _rAccessor, m_pImpl->aConfigRoot.getNodeValue( _rAccessor.getPath() ), m_pImpl->rMutex );
456 //.........................................................................
457 } // namespace utl
458 //.........................................................................