1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "precompiled_sd.hxx"
29 
30 #include "framework/Configuration.hxx"
31 
32 #include "framework/FrameworkHelper.hxx"
33 #include <comphelper/stl_types.hxx>
34 
35 
36 
37 using namespace ::com::sun::star;
38 using namespace ::com::sun::star::uno;
39 using namespace ::com::sun::star::drawing::framework;
40 using ::sd::framework::FrameworkHelper;
41 using ::rtl::OUString;
42 
43 #undef VERBOSE
44 
45 namespace {
46 /** Use the XResourceId::compareTo() method to implement a compare operator
47     for STL containers.
48 */
49 class XResourceIdLess
50     : 	public ::std::binary_function <Reference<XResourceId>, Reference<XResourceId>, bool>
51 {
52 public:
53     bool operator () (const Reference<XResourceId>& rId1, const Reference<XResourceId>& rId2) const
54 	{
55         return rId1->compareTo(rId2) == -1;
56     }
57 };
58 
59 } // end of anonymous namespace
60 
61 
62 
63 
64 namespace sd { namespace framework {
65 
66 
67 class Configuration::ResourceContainer
68     : public ::std::set<Reference<XResourceId>, XResourceIdLess>
69 {
70 public:
71     ResourceContainer (void) {}
72 };
73 
74 
75 
76 
77 //----- Service ---------------------------------------------------------------
78 
79 Reference<XInterface> SAL_CALL Configuration_createInstance (
80     const Reference<XComponentContext>& rxContext)
81 {
82     (void)rxContext;
83     return Reference<XInterface>(static_cast<XWeak*>(new Configuration(NULL,false)));
84 }
85 
86 
87 
88 
89 OUString Configuration_getImplementationName (void) throw(RuntimeException)
90 {
91     return OUString(RTL_CONSTASCII_USTRINGPARAM(
92         "com.sun.star.comp.Draw.framework.configuration.Configuration"));
93 }
94 
95 
96 
97 
98 Sequence<rtl::OUString> SAL_CALL Configuration_getSupportedServiceNames (void)
99     throw (RuntimeException)
100 {
101 	static const OUString sServiceName(OUString::createFromAscii(
102         "com.sun.star.drawing.framework.Configuration"));
103 	return Sequence<rtl::OUString>(&sServiceName, 1);
104 }
105 
106 
107 
108 
109 //===== Configuration =========================================================
110 
111 Configuration::Configuration (
112     const Reference<XConfigurationControllerBroadcaster>& rxBroadcaster,
113     bool bBroadcastRequestEvents)
114     : ConfigurationInterfaceBase(MutexOwner::maMutex),
115       mpResourceContainer(new ResourceContainer()),
116       mxBroadcaster(rxBroadcaster),
117       mbBroadcastRequestEvents(bBroadcastRequestEvents)
118 {
119 }
120 
121 
122 
123 Configuration::Configuration (
124     const Reference<XConfigurationControllerBroadcaster>& rxBroadcaster,
125     bool bBroadcastRequestEvents,
126     const ResourceContainer& rResourceContainer)
127     : ConfigurationInterfaceBase(MutexOwner::maMutex),
128       mpResourceContainer(new ResourceContainer(rResourceContainer)),
129       mxBroadcaster(rxBroadcaster),
130       mbBroadcastRequestEvents(bBroadcastRequestEvents)
131 {
132 }
133 
134 
135 
136 
137 Configuration::~Configuration (void)
138 {
139 }
140 
141 
142 
143 
144 void SAL_CALL Configuration::disposing (void)
145 {
146     ::osl::MutexGuard aGuard (maMutex);
147     mpResourceContainer->clear();
148     mxBroadcaster = NULL;
149 }
150 
151 
152 
153 
154 //----- XConfiguration --------------------------------------------------------
155 
156 void SAL_CALL Configuration::addResource (const Reference<XResourceId>& rxResourceId)
157     throw (RuntimeException)
158 {
159     ThrowIfDisposed();
160 
161     if ( ! rxResourceId.is() || rxResourceId->getResourceURL().getLength()==0)
162         throw ::com::sun::star::lang::IllegalArgumentException();
163 
164     if (mpResourceContainer->find(rxResourceId) == mpResourceContainer->end())
165     {
166 #ifdef VERBOSE
167     OSL_TRACE("Configuration::addResource() %s",
168         OUStringToOString(
169             FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
170 #endif
171         mpResourceContainer->insert(rxResourceId);
172         PostEvent(rxResourceId, true);
173     }
174 }
175 
176 
177 
178 
179 void SAL_CALL Configuration::removeResource (const Reference<XResourceId>& rxResourceId)
180     throw (RuntimeException)
181 {
182     ThrowIfDisposed();
183 
184     if ( ! rxResourceId.is() || rxResourceId->getResourceURL().getLength()==0)
185         throw ::com::sun::star::lang::IllegalArgumentException();
186 
187     ResourceContainer::iterator iResource (mpResourceContainer->find(rxResourceId));
188     if (iResource != mpResourceContainer->end())
189     {
190 #ifdef VERBOSE
191     OSL_TRACE("Configuration::removeResource() %s",
192         OUStringToOString(
193             FrameworkHelper::ResourceIdToString(rxResourceId), RTL_TEXTENCODING_UTF8).getStr());
194 #endif
195         PostEvent(rxResourceId,false);
196         mpResourceContainer->erase(iResource);
197     }
198 }
199 
200 
201 
202 
203 Sequence<Reference<XResourceId> > SAL_CALL Configuration::getResources (
204     const Reference<XResourceId>& rxAnchorId,
205     const ::rtl::OUString& rsResourceURLPrefix,
206     AnchorBindingMode eMode)
207     throw (::com::sun::star::uno::RuntimeException)
208 {
209     ::osl::MutexGuard aGuard (maMutex);
210     ThrowIfDisposed();
211 
212     bool bFilterResources (rsResourceURLPrefix.getLength() > 0);
213 
214     // Collect the matching resources in a vector.
215     ::std::vector<Reference<XResourceId> > aResources;
216     ResourceContainer::const_iterator iResource;
217     for (iResource=mpResourceContainer->begin();
218          iResource!=mpResourceContainer->end();
219          ++iResource)
220     {
221         if ( ! (*iResource)->isBoundTo(rxAnchorId,eMode))
222             continue;
223 
224 
225         if (bFilterResources)
226         {
227             // Apply the given resource prefix as filter.
228 
229             // Make sure that the resource is bound directly to the anchor.
230             if (eMode != AnchorBindingMode_DIRECT
231                 && ! (*iResource)->isBoundTo(rxAnchorId, AnchorBindingMode_DIRECT))
232             {
233                 continue;
234             }
235 
236             // Make sure that the resource URL matches the given prefix.
237             if ( ! (*iResource)->getResourceURL().match(rsResourceURLPrefix))
238             {
239                 continue;
240             }
241         }
242 
243         aResources.push_back(*iResource);
244     }
245 
246     // Copy the resources from the vector into a new sequence.
247     Sequence<Reference<XResourceId> > aResult (aResources.size());
248     for (sal_uInt32 nIndex=0; nIndex<aResources.size(); ++nIndex)
249         aResult[nIndex] = aResources[nIndex];
250 
251     return aResult;
252 }
253 
254 
255 
256 
257 sal_Bool SAL_CALL Configuration::hasResource (const Reference<XResourceId>& rxResourceId)
258     throw (RuntimeException)
259 {
260     ::osl::MutexGuard aGuard (maMutex);
261     ThrowIfDisposed();
262 
263     return rxResourceId.is()
264         && mpResourceContainer->find(rxResourceId) != mpResourceContainer->end();
265 }
266 
267 
268 
269 
270 //----- XCloneable ------------------------------------------------------------
271 
272 Reference<util::XCloneable> SAL_CALL Configuration::createClone (void)
273     throw (RuntimeException)
274 {
275     ::osl::MutexGuard aGuard (maMutex);
276     ThrowIfDisposed();
277 
278     Configuration* pConfiguration = new Configuration(
279         mxBroadcaster,
280         mbBroadcastRequestEvents,
281         *mpResourceContainer);
282 
283     return Reference<util::XCloneable>(pConfiguration);
284 }
285 
286 
287 
288 
289 //----- XNamed ----------------------------------------------------------------
290 
291 OUString SAL_CALL Configuration::getName (void)
292     throw (RuntimeException)
293 {
294     ::osl::MutexGuard aGuard (maMutex);
295     OUString aString;
296 
297 	if (rBHelper.bDisposed || rBHelper.bInDispose)
298         aString += OUString::createFromAscii("DISPOSED ");
299     aString += OUString::createFromAscii("Configuration[");
300 
301     ResourceContainer::const_iterator iResource;
302     for (iResource=mpResourceContainer->begin();
303          iResource!=mpResourceContainer->end();
304          ++iResource)
305     {
306         if (iResource != mpResourceContainer->begin())
307             aString += OUString::createFromAscii(", ");
308         aString += FrameworkHelper::ResourceIdToString(*iResource);
309     }
310     aString += OUString::createFromAscii("]");
311 
312     return aString;
313 }
314 
315 
316 
317 
318 void SAL_CALL Configuration::setName (const OUString& rsName)
319     throw (RuntimeException)
320 {
321     (void)rsName; // rsName is ignored.
322 }
323 
324 
325 
326 
327 
328 // ----------------------------------------------------------------------------
329 
330 void Configuration::PostEvent (
331     const Reference<XResourceId>& rxResourceId,
332     const bool bActivation)
333 {
334     OSL_ASSERT(rxResourceId.is());
335 
336     if (mxBroadcaster.is())
337     {
338         ConfigurationChangeEvent aEvent;
339         aEvent.ResourceId = rxResourceId;
340         if (bActivation)
341             if (mbBroadcastRequestEvents)
342                 aEvent.Type = FrameworkHelper::msResourceActivationRequestEvent;
343             else
344                 aEvent.Type = FrameworkHelper::msResourceActivationEvent;
345         else
346             if (mbBroadcastRequestEvents)
347                 aEvent.Type = FrameworkHelper::msResourceDeactivationRequestEvent;
348             else
349                 aEvent.Type = FrameworkHelper::msResourceDeactivationEvent;
350         aEvent.Configuration = this;
351 
352         mxBroadcaster->notifyEvent(aEvent);
353     }
354 }
355 
356 
357 
358 
359 void Configuration::ThrowIfDisposed (void) const
360     throw (::com::sun::star::lang::DisposedException)
361 {
362 	if (rBHelper.bDisposed || rBHelper.bInDispose)
363 	{
364         throw lang::DisposedException (
365             OUString(RTL_CONSTASCII_USTRINGPARAM(
366                 "Configuration object has already been disposed")),
367             const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
368     }
369 }
370 
371 
372 
373 
374 //=============================================================================
375 
376 bool AreConfigurationsEquivalent (
377     const Reference<XConfiguration>& rxConfiguration1,
378     const Reference<XConfiguration>& rxConfiguration2)
379 {
380     if (rxConfiguration1.is() != rxConfiguration2.is())
381         return false;
382     if ( ! rxConfiguration1.is() && ! rxConfiguration2.is())
383         return true;
384 
385     // Get the lists of resources from the two given configurations.
386     const Sequence<Reference<XResourceId> > aResources1(
387         rxConfiguration1->getResources(
388             NULL, OUString(), AnchorBindingMode_INDIRECT));
389     const Sequence<Reference<XResourceId> > aResources2(
390         rxConfiguration2->getResources(
391             NULL, OUString(), AnchorBindingMode_INDIRECT));
392 
393     // When the number of resources differ then the configurations can not
394     // be equivalent.
395     const sal_Int32 nCount (aResources1.getLength());
396     const sal_Int32 nCount2 (aResources2.getLength());
397     if (nCount != nCount2)
398         return false;
399 
400     // Comparison of the two lists of resource ids relies on their
401     // ordering.
402     for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex)
403     {
404         const Reference<XResourceId> xResource1 (aResources1[nIndex]);
405         const Reference<XResourceId> xResource2 (aResources2[nIndex]);
406         if (xResource1.is() && xResource2.is())
407         {
408             if (xResource1->compareTo(xResource2) != 0)
409                 return false;
410         }
411         else if (xResource1.is() != xResource2.is())
412         {
413             return false;
414         }
415     }
416 
417     return true;
418 }
419 
420 } } // end of namespace sd::framework
421