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 
24 #ifndef SD_FRAMEWORK_CONFIGURATION_UPDATER_HXX
25 #define SD_FRAMEWORK_CONFIGURATION_UPDATER_HXX
26 
27 #include "ConfigurationControllerResourceManager.hxx"
28 #include <com/sun/star/drawing/framework/XResourceId.hpp>
29 #include <com/sun/star/drawing/framework/XConfiguration.hpp>
30 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
31 #include <vcl/timer.hxx>
32 #include <vector>
33 #include <boost/shared_ptr.hpp>
34 
35 namespace css = ::com::sun::star;
36 
37 namespace sd { namespace framework {
38 
39 class ConfigurationClassifier;
40 class ConfigurationUpdaterLock;
41 
42 /** This is a helper class for the ConfigurationController.  It handles the
43     update of the current configuration so that it looks like a requested
44     configuration.  An update is made by activating or deactivating drawing
45     framework resources.
46 
47     When an update is not successful, i.e. after the update the current
48     configuration is not equivalent to the requested configuration, then a
49     timer is started to repeat the update after a short time.
50 */
51 class ConfigurationUpdater
52 {
53 public:
54     /** Create a new ConfigurationUpdater object that notifies configuration
55         changes and the start and end of updates via the given broadcaster.
56     */
57     ConfigurationUpdater (
58         const ::boost::shared_ptr<ConfigurationControllerBroadcaster>& rpBroadcaster,
59         const ::boost::shared_ptr<ConfigurationControllerResourceManager>& rpResourceManager,
60         const css::uno::Reference<
61             css::drawing::framework::XControllerManager>& rxControllerManager);
62     ~ConfigurationUpdater (void);
63 
64     /** This method is typically called once, when the controller manager is
65         accessible to the caller.
66     */
67     void SetControllerManager(
68         const css::uno::Reference<
69             css::drawing::framework::XControllerManager>& rxControllerManager);
70 
71     /** Request an update of the current configuration so that it looks like
72         the given requested configuration.  It checks whether an update of
73         the current configuration can be done.  Calls UpdateConfiguration()
74         if that is the case.  Otherwise it schedules a later call to
75         UpdateConfiguration().
76     */
77     void RequestUpdate (const css::uno::Reference<
78         css::drawing::framework::XConfiguration>& rxRequestedConfiguration);
79 
80     css::uno::Reference<
81         css::drawing::framework::XConfiguration> GetCurrentConfiguration (void) const;
82 
83     friend class ConfigurationUpdaterLock;
84     /** Return a lock of the called ConfigurationUpdater.  While the
85         returned object exists no update of the current configuration is
86         made.
87     */
88     ::boost::shared_ptr<ConfigurationUpdaterLock> GetLock (void);
89 
90 private:
91     /** A reference to the XControllerManager is kept so that
92         UpdateConfiguration() has access to the other sub controllers.
93     */
94     css::uno::Reference<
95         css::drawing::framework::XControllerManager> mxControllerManager;
96 
97     ::boost::shared_ptr<ConfigurationControllerBroadcaster> mpBroadcaster;
98 
99     /** The current configuration holds the resources that are currently
100         active.  It is modified during an update.
101     */
102     css::uno::Reference<
103         css::drawing::framework::XConfiguration> mxCurrentConfiguration;
104 
105     /** The requested configuration holds the resources that have been
106         requested to activate or to deactivate since the last update.  It is
107         (usually) not modified during an update.  This configuration is
108         maintained by the ConfigurationController and given to the
109         ConfigurationUpdater in the RequestUpdate() method.
110     */
111     css::uno::Reference<
112         css::drawing::framework::XConfiguration> mxRequestedConfiguration;
113 
114     /** This flag is set to </sal_True> when an update of the current
115         configurtion was requested (because the last request in the queue
116         was processed) but could not be exected because the
117         ConfigurationController was locked.  A call to UpdateConfiguration()
118         resets the flag to </sal_False>.
119     */
120     bool mbUpdatePending;
121 
122     /** This flag is set to </sal_True> while the UpdateConfiguration() method
123         is running.  It is used to prevent reentrance problems with this
124         method.
125     */
126     bool mbUpdateBeingProcessed;
127 
128     /** The ConfigurationController is locked when this count has a value
129         larger then zero.  If the controller is locked then updates of the
130         current configuration are not made.
131     */
132     sal_Int32 mnLockCount;
133 
134     /** This timer is used to check from time to time whether the requested
135         configuration and the current configuration are identcal and request
136         an update when they are not.
137         This is used to overcome problems with resources that become
138         available asynchronously.
139     */
140     Timer maUpdateTimer;
141 
142     /** The number of failed updates (those after which the current
143         configuration is not equivalent to the requested configuration) is
144         used to determine how long to wait before another update is made.
145     */
146     sal_Int32 mnFailedUpdateCount;
147 
148     ::boost::shared_ptr<ConfigurationControllerResourceManager> mpResourceManager;
149 
150     /** This method does the main work of an update.  It calls the sub
151         controllers that are responsible for the various types of resources
152         and tells them to update their active resources.  It notifies
153         listeners about the start and end of the configuration update.
154     */
155     void UpdateConfiguration (void);
156 
157     /** Basically calls UpdaterStart() andUpdateEnd() and makes some debug
158         output.
159     */
160     void UpdateCore (const ConfigurationClassifier& rClassifier);
161 
162     /** Check for all pure anchors if they have at least one child.
163         Childless pure anchors are deactivated.
164         This affects only the current configuration.
165     */
166     void CheckPureAnchors (
167         const css::uno::Reference<css::drawing::framework::XConfiguration>& rxConfiguration,
168         ::std::vector<css::uno::Reference<css::drawing::framework::XResourceId> >&
169             rResourcesToDeactivate);
170 
171     /** Remove from the requested configration all pure anchors that have no
172         child.  Requested but not yet activated anchors can not be removed
173         because without the actual resource the 'pureness' of an anchor can
174         not be determined.
175     */
176     void CleanRequestedConfiguration (void);
177 
178     /** Check the success of a recently executed configuration update.
179         When the update failed then start the timer.
180     */
181     void CheckUpdateSuccess (void);
182 
183     /** This method sets the mbUpdateBeingProcessed member that is used to
184         prevent reentrance problems.  This method allows function objects
185         easyly and safely to modify the variable.
186     */
187     void SetUpdateBeingProcessed (bool bValue);
188 
189     /** Return whether it is possible to do an update of the configuration.
190         This takes into account whether another update is currently being
191         executed, the lock count, and whether the configuration controller
192         is still valid.
193     */
194     bool IsUpdatePossible (void);
195 
196     /** Lock updates of the current configuration.  For intermediate requests
197         for updates mbUpdatePending is set to <TRUE/>.
198     */
199     void LockUpdates (void);
200 
201     /** When an update was requested since the last LockUpdates() call then
202         RequestUpdate() is called.
203     */
204     void UnlockUpdates (void);
205 
206     DECL_LINK(TimeoutHandler, Timer*);
207 };
208 
209 } } // end of namespace sd::framework
210 
211 #endif
212