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 #include "unotools/unotoolsdllapi.h"
24 
25 #ifndef UNOTOOLS_CONFIGVALUECONTAINER_HXX
26 #define UNOTOOLS_CONFIGVALUECONTAINER_HXX
27 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 #include <osl/mutex.hxx>
29 
30 //.........................................................................
31 namespace utl
32 {
33 //.........................................................................
34 
35 #define CVC_READONLY_ACCESS		0x0000
36 #define CVC_UPDATE_ACCESS		0x0001
37 
38 #define CVC_LAZY_UPDATE			0x0000
39 #define CVC_IMMEDIATE_UPDATE	0x0002
40 
41 	struct OConfigurationValueContainerImpl;
42 	struct NodeValueAccessor;
43 	//=====================================================================
44 	//= OConfigurationValueContainer
45 	//=====================================================================
46 	/** allows simple access to static configuration structures.
47 
48 		<p>The basic idea of this class is that it's clients (usually derived classes) simply register an
49 		address in memory and a node path, and upon explicit request, the configuration value and the memory
50 		are syncronized.<br/>
51 		This means that when calling <method>read</method>, the current configuration values are copied into
52 		the memory registered for them, and upon calling <method>write</method> the current values in memory
53 		are set in the configuration nodes.</p>
54 
55 		<p>This way, the usage of this class is pretty straight forward: derive your own class, spend some members
56 		to it, and bind these members to configuration node (usually done in the ctor of the derived class).<br/>
57 		In the dtor, simply call <method>write</method> and <method>commit</method>.</p>
58 
59 		<p>There is no auto-commit mechanism in the dtor: In the usual scenario, when you derive from this class
60 		and bind some members of your derived class to config nodes, this means that your members will be destroyed
61 		before your base class' dtor is called, so accessing the memory during such a theoretical auto-commit would
62 		yield undefined behaviour.</p>
63 	*/
64 	class UNOTOOLS_DLLPUBLIC OConfigurationValueContainer
65 	{
66 	private:
67 		OConfigurationValueContainerImpl*
68 					m_pImpl;
69 
70 	protected:
71 		const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&
72 					getServiceFactory( ) const;
73 
74 	protected:
75 		//-----------------------------------------------------------------
76 		// construction/destruction
77 
78 		/** constructs the object
79 
80 			@param _rxORB
81 				specifies the service factory which should be used to access the configuration
82 			@param _rAccessSafety
83 				As this class is intented to manipulate objects it does not hold itself (see the various
84 				registerXXX methods), it needs to guard these access for muti threading safety.<br/>
85 				The mutex given here is locked whenever such an access occurs.
86 			@param _pConfigLocation
87 				is an ASCII string describing the configurations node path
88 			@param _nAccessFlags
89 				specifies different aspects of the configuration aspect to be created, e.g. it's update mode etc.<br/>
90 				See the CVC_xxx constants for what you can use here.
91 			@param _nLevels
92 				specifies the number of levels to access under the node given by <arg>_pConfigLocation</arg>
93 		*/
94 		OConfigurationValueContainer(
95 			const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
96 			::osl::Mutex& _rAccessSafety,
97 			const sal_Char* _pConfigLocation,
98 			const sal_uInt16 _nAccessFlags = CVC_UPDATE_ACCESS | CVC_LAZY_UPDATE,
99 			const sal_Int32 _nLevels = -1
100 		);
101 
102 		/** constructs the object
103 
104 			@param _rxORB
105 				specifies the service factory which should be used to access the configuration
106 			@param _rAccessSafety
107 				As this class is intented to manipulate objects it does not hold itself (see the various
108 				registerXXX methods), it needs to guard these access for muti threading safety.<br/>
109 				The mutex given here is locked whenever such an access occurs.
110 			@param _rConfigLocation
111 				describes the configurations node path
112 			@param _nAccessFlags
113 				specifies different aspects of the configuration aspect to be created, e.g. it's update mode etc.<br/>
114 				See the CVC_xxx constants for what you can use here.
115 			@param _nLevels
116 				specifies the number of levels to access under the node given by <arg>_pConfigLocation</arg>
117 		*/
118 		OConfigurationValueContainer(
119 			const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
120 			::osl::Mutex& _rAccessSafety,
121 			const ::rtl::OUString& _rConfigLocation,
122 			const sal_uInt16 _nAccessFlags = CVC_UPDATE_ACCESS | CVC_LAZY_UPDATE,
123 			const sal_Int32 _nLevels = -1
124 		);
125 
126 		/// dtor
127 		~OConfigurationValueContainer();
128 
129 		//-----------------------------------------------------------------
130 		// registering data containers
131 
132 		/** registers a data accessor of an arbitrary type.
133 
134 			<p>Usually, in your derived class you simply add a member of the correct type of the configuration
135 			value, and then call this method with the address of this member.</p>
136 
137 			<p>If the value you want to access may be <NULL/> at runtime, and if you want to recognize such
138 			<NULL/> values, you may consider using <method>registerNullValueExchangeLocation</method>.</p>
139 
140 			@param _pRelativePathAscii
141 				is a relative (ASCII) path of the node which should be "mirrored" into the accessor.
142 			@param _pContainer
143 				points to the accessors location in memory. Usually, this is simply an address of your derived class
144 			@param _rValueType
145 				is the type of your accessort. This type must be supported by the configuration.
146 		*/
147 		void	registerExchangeLocation(
148 			const sal_Char* _pRelativePathAscii,
149 			void* _pContainer,
150 			const ::com::sun::star::uno::Type& _rValueType
151 		);
152 
153 		/** registers a data accessor of an arbitrary type.
154 
155 			<p>Usually, in your derived class you simply add a member of type <type scope="com.sun.star.uno">Any</type>,
156 			and then call this method with the address of this member.</p>
157 
158 			@param _pRelativePathAscii
159 				is a relative (ASCII) path of the node which should be "mirrored" into the accessor.
160 			@param _pContainer
161 				points to the Any you want to hold the value
162 		*/
163 		void	registerNullValueExchangeLocation(
164 			const sal_Char* _pRelativePathAscii,
165 			::com::sun::star::uno::Any* _pContainer
166 		);
167 
168 	public:
169 		/** reads the configuration data
170 
171 			<p>The current values of the nodes bound (using the registerXXX methods) is copied into their
172 			respective exchange locations.</p>
173 
174 			<p>Please note that any changes done to your exchange locations are overridden with the current config
175 			values.</p>
176 
177 			@see write
178 		*/
179 		void	read( );
180 
181 		/** updates the configuration data
182 
183 			<p>The current values in memory (your exchange locations registered using the registerXXX methods) is
184 			forwarded to their respective configuration nodes.</p>
185 
186 			<p>Note that calling <method>write</method>(<sal_True/) is the same as calling <method>commit</method>(<TRUE/>).</p>
187 
188 			@precond
189 				The access must have been created for update access
190 
191 			@param _bCommit
192 				If set to <TRUE/>, an automatic commit is done after the values have been synchronized.<br/>
193 				If set to <FALSE/>, you must explicitly call <method>commit</method> to make your changes persistent.
194 
195 			@see read
196 			@see commit
197 		*/
198 		void	write( sal_Bool _bCommit = sal_True );
199 
200 		/** commits any changes done
201 
202 			<p>Note that calling <method>write</method>(<sal_True/) is the same as calling <method>commit</method>(<TRUE/>).</p>
203 
204 			@precond
205 				The access must have been created for update access
206 
207 			@param _bWrite
208 				If <TRUE/>, the current values in the exchange locations are written to the configuration nodes
209 				before the changes are committed.<br/>
210 				If <FALSE/>, only the current values in the config nodes (as present since the last call to
211 				<method>write</method>) are committed.
212 		*/
213 		void	commit( sal_Bool _bWrite = sal_True );
214 
215 	private:
216 		/// implements the ctors
217 		void implConstruct(
218 			const ::rtl::OUString& _rConfigLocation,
219 			const sal_uInt16 _nAccessFlags,
220 			const sal_Int32 _nLevels
221 		);
222 
223 		/// registers a value container
224 		void	implRegisterExchangeLocation( const NodeValueAccessor& _rAccessor );
225 	};
226 
227 //.........................................................................
228 }	// namespace utl
229 //.........................................................................
230 
231 #endif // UNOTOOLS_CONFIGVALUECONTAINER_HXX
232 
233