bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / framework / configuration / ResourceId.cxx
blob3f343c989069a5f6d087cc752af421f57666dc7f
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 "framework/ResourceId.hxx"
21 #include "framework/FrameworkHelper.hxx"
22 #include "tools/SdGlobalResourceContainer.hxx"
23 #include <com/sun/star/lang/IllegalArgumentException.hpp>
24 #include <com/sun/star/uno/XComponentContext.hpp>
25 #include <com/sun/star/util/URLTransformer.hpp>
26 #include <comphelper/processfactory.hxx>
27 #include <rtl/ref.hxx>
29 #include <facreg.hxx>
31 using namespace ::com::sun::star;
32 using namespace ::com::sun::star::uno;
33 using namespace ::com::sun::star::lang;
34 using namespace ::com::sun::star::drawing::framework;
36 /** When the USE_OPTIMIZATIONS symbol is defined then at some optimizations
37 are activated that work only together with XResourceId objects that are
38 implemented by the ResourceId class. For other implementations of when
39 the USE_OPTIMIZATIONS symbol is not defined then alternative code is
40 used instead.
42 #define USE_OPTIMIZATIONS
44 namespace sd { namespace framework {
46 //===== ResourceId ============================================================
48 WeakReference<util::XURLTransformer> ResourceId::mxURLTransformerWeak;
50 ResourceId::ResourceId()
51 : ResourceIdInterfaceBase(),
52 maResourceURLs(0),
53 mpURL()
57 ResourceId::ResourceId (
58 const std::vector<OUString>& rResourceURLs)
59 : ResourceIdInterfaceBase(),
60 maResourceURLs(rResourceURLs),
61 mpURL()
63 ParseResourceURL();
66 ResourceId::ResourceId (
67 const OUString& rsResourceURL)
68 : ResourceIdInterfaceBase(),
69 maResourceURLs(1, rsResourceURL),
70 mpURL()
72 // Handle the special case of an empty resource URL.
73 if (rsResourceURL.isEmpty())
74 maResourceURLs.clear();
75 ParseResourceURL();
78 ResourceId::ResourceId (
79 const OUString& rsResourceURL,
80 const OUString& rsAnchorURL)
81 : ResourceIdInterfaceBase(),
82 maResourceURLs(2),
83 mpURL()
85 maResourceURLs[0] = rsResourceURL;
86 maResourceURLs[1] = rsAnchorURL;
87 ParseResourceURL();
90 ResourceId::ResourceId (
91 const OUString& rsResourceURL,
92 const OUString& rsFirstAnchorURL,
93 const Sequence<OUString>& rAnchorURLs)
94 : ResourceIdInterfaceBase(),
95 maResourceURLs(2+rAnchorURLs.getLength()),
96 mpURL()
98 maResourceURLs[0] = rsResourceURL;
99 maResourceURLs[1] = rsFirstAnchorURL;
100 for (sal_Int32 nIndex=0; nIndex<rAnchorURLs.getLength(); ++nIndex)
101 maResourceURLs[nIndex+2] = rAnchorURLs[nIndex];
102 ParseResourceURL();
105 ResourceId::~ResourceId()
107 mpURL.reset();
110 OUString SAL_CALL
111 ResourceId::getResourceURL()
112 throw(com::sun::star::uno::RuntimeException, std::exception)
114 if (!maResourceURLs.empty())
115 return maResourceURLs[0];
116 else
117 return OUString();
120 util::URL SAL_CALL
121 ResourceId::getFullResourceURL()
122 throw(com::sun::star::uno::RuntimeException, std::exception)
124 if (mpURL.get() != NULL)
125 return *mpURL;
127 Reference<util::XURLTransformer> xURLTransformer (mxURLTransformerWeak);
128 if (xURLTransformer.is() && !maResourceURLs.empty() )
130 mpURL.reset(new util::URL);
131 mpURL->Complete = maResourceURLs[0];
132 xURLTransformer->parseStrict(*mpURL);
133 return *mpURL;
136 util::URL aURL;
137 if (!maResourceURLs.empty())
138 aURL.Complete = maResourceURLs[0];
139 return aURL;
142 sal_Bool SAL_CALL
143 ResourceId::hasAnchor()
144 throw (RuntimeException, std::exception)
146 return maResourceURLs.size()>1;
149 Reference<XResourceId> SAL_CALL
150 ResourceId::getAnchor()
151 throw (RuntimeException, std::exception)
153 ::rtl::Reference<ResourceId> rResourceId (new ResourceId());
154 const sal_Int32 nAnchorCount (maResourceURLs.size()-1);
155 if (nAnchorCount > 0)
157 rResourceId->maResourceURLs.resize(nAnchorCount);
158 for (sal_Int32 nIndex=0; nIndex<nAnchorCount; ++nIndex)
159 rResourceId->maResourceURLs[nIndex] = maResourceURLs[nIndex+1];
161 return Reference<XResourceId>(rResourceId.get());
164 Sequence<OUString> SAL_CALL
165 ResourceId::getAnchorURLs()
166 throw (RuntimeException, std::exception)
168 const sal_Int32 nAnchorCount (maResourceURLs.size() - 1);
169 if (nAnchorCount > 0)
171 Sequence<OUString> aAnchorURLs (nAnchorCount);
172 for (sal_Int32 nIndex=0; nIndex<nAnchorCount; ++nIndex)
173 aAnchorURLs[nIndex] = maResourceURLs[nIndex+1];
174 return aAnchorURLs;
176 else
177 return Sequence<OUString>();
180 OUString SAL_CALL
181 ResourceId::getResourceTypePrefix()
182 throw (RuntimeException, std::exception)
184 if (!maResourceURLs.empty() )
186 // Return the "private:resource/<type>/" prefix.
188 // Get the prefix that ends with the second "/".
189 const OUString& rsResourceURL (maResourceURLs[0]);
190 sal_Int32 nPrefixEnd (rsResourceURL.indexOf('/', 0));
191 if (nPrefixEnd >= 0)
192 nPrefixEnd = rsResourceURL.indexOf('/', nPrefixEnd+1) + 1;
193 else
194 nPrefixEnd = 0;
196 return rsResourceURL.copy(0,nPrefixEnd);
198 else
199 return OUString();
202 sal_Int16 SAL_CALL
203 ResourceId::compareTo (const Reference<XResourceId>& rxResourceId)
204 throw (RuntimeException, std::exception)
206 sal_Int16 nResult (0);
208 if ( ! rxResourceId.is())
210 // The empty reference is interpreted as empty resource id object.
211 if (!maResourceURLs.empty())
212 nResult = +1;
213 else
214 nResult = 0;
216 else
218 ResourceId* pId = NULL;
219 #ifdef USE_OPTIMIZATIONS
220 pId = dynamic_cast<ResourceId*>(rxResourceId.get());
221 #endif
222 if (pId != NULL)
224 // We have direct access to the implementation of the given
225 // resource id object.
226 nResult = CompareToLocalImplementation(*pId);
228 else
230 // We have to do the comparison via the UNO interface of the
231 // given resource id object.
232 nResult = CompareToExternalImplementation(rxResourceId);
236 return nResult;
239 sal_Int16 ResourceId::CompareToLocalImplementation (const ResourceId& rId) const
241 sal_Int16 nResult (0);
243 const sal_uInt32 nLocalURLCount (maResourceURLs.size());
244 const sal_uInt32 nURLCount(rId.maResourceURLs.size());
246 // Start comparison with the top most anchors.
247 for (sal_Int32 nIndex=nURLCount-1,nLocalIndex=nLocalURLCount-1;
248 nIndex>=0 && nLocalIndex>=0;
249 --nIndex,--nLocalIndex)
251 const OUString sLocalURL (maResourceURLs[nLocalIndex]);
252 const OUString sURL (rId.maResourceURLs[nIndex]);
253 const sal_Int32 nLocalResult (sURL.compareTo(sLocalURL));
254 if (nLocalResult != 0)
256 if (nLocalResult < 0)
257 nResult = -1;
258 else
259 nResult = +1;
260 break;
264 if (nResult == 0)
266 // No difference found yet. When the lengths are the same then the
267 // two resource ids are equivalent. Otherwise the shorter comes
268 // first.
269 if (nLocalURLCount != nURLCount)
271 if (nLocalURLCount < nURLCount)
272 nResult = -1;
273 else
274 nResult = +1;
278 return nResult;
281 sal_Int16 ResourceId::CompareToExternalImplementation (const Reference<XResourceId>& rxId) const
283 sal_Int16 nResult (0);
285 const Sequence<OUString> aAnchorURLs (rxId->getAnchorURLs());
286 const sal_uInt32 nLocalURLCount (maResourceURLs.size());
287 const sal_uInt32 nURLCount(1+aAnchorURLs.getLength());
289 // Start comparison with the top most anchors.
290 sal_Int32 nLocalResult (0);
291 for (sal_Int32 nIndex=nURLCount-1,nLocalIndex=nLocalURLCount-1;
292 nIndex>=0&&nLocalIndex>=0;
293 --nIndex,--nLocalIndex)
295 if (nIndex == 0 )
296 nLocalResult = maResourceURLs[nIndex].compareTo(rxId->getResourceURL());
297 else
298 nLocalResult = maResourceURLs[nIndex].compareTo(aAnchorURLs[nIndex-1]);
299 if (nLocalResult != 0)
301 if (nLocalResult < 0)
302 nResult = -1;
303 else
304 nResult = +1;
305 break;
309 if (nResult == 0)
311 // No difference found yet. When the lengths are the same then the
312 // two resource ids are equivalent. Otherwise the shorter comes
313 // first.
314 if (nLocalURLCount != nURLCount)
316 if (nLocalURLCount < nURLCount)
317 nResult = -1;
318 else
319 nResult = +1;
323 return nResult;
326 sal_Bool SAL_CALL
327 ResourceId::isBoundTo (
328 const Reference<XResourceId>& rxResourceId,
329 AnchorBindingMode eMode)
330 throw (RuntimeException, std::exception)
332 if ( ! rxResourceId.is())
334 // An empty reference is interpreted as empty resource id.
335 return IsBoundToAnchor(NULL, NULL, eMode);
338 ResourceId* pId = NULL;
339 #ifdef USE_OPTIMIZATIONS
340 pId = dynamic_cast<ResourceId*>(rxResourceId.get());
341 #endif
342 if (pId != NULL)
344 return IsBoundToAnchor(pId->maResourceURLs, eMode);
346 else
348 const OUString sResourceURL (rxResourceId->getResourceURL());
349 const Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs());
350 return IsBoundToAnchor(&sResourceURL, &aAnchorURLs, eMode);
354 sal_Bool SAL_CALL
355 ResourceId::isBoundToURL (
356 const OUString& rsAnchorURL,
357 AnchorBindingMode eMode)
358 throw (RuntimeException, std::exception)
360 return IsBoundToAnchor(&rsAnchorURL, NULL, eMode);
363 Reference<XResourceId> SAL_CALL
364 ResourceId::clone()
365 throw(RuntimeException, std::exception)
367 return new ResourceId(maResourceURLs);
370 //----- XInitialization -------------------------------------------------------
372 void SAL_CALL ResourceId::initialize (const Sequence<Any>& aArguments)
373 throw (RuntimeException, std::exception)
375 sal_uInt32 nCount (aArguments.getLength());
376 for (sal_uInt32 nIndex=0; nIndex<nCount; ++nIndex)
378 OUString sResourceURL;
379 if (aArguments[nIndex] >>= sResourceURL)
380 maResourceURLs.push_back(sResourceURL);
381 else
383 Reference<XResourceId> xAnchor;
384 if (aArguments[nIndex] >>= xAnchor)
386 if (xAnchor.is())
388 maResourceURLs.push_back(xAnchor->getResourceURL());
389 Sequence<OUString> aAnchorURLs (xAnchor->getAnchorURLs());
390 for (sal_Int32 nURLIndex=0; nURLIndex<aAnchorURLs.getLength(); ++nURLIndex)
392 maResourceURLs.push_back(aAnchorURLs[nURLIndex]);
398 ParseResourceURL();
401 OUString ResourceId::getImplementationName()
402 throw (css::uno::RuntimeException, std::exception)
404 return OUString("com.sun.star.comp.Draw.framework.ResourceId");
407 sal_Bool ResourceId::supportsService(OUString const & ServiceName)
408 throw (css::uno::RuntimeException, std::exception)
410 return cppu::supportsService(this, ServiceName);
413 css::uno::Sequence<OUString> ResourceId::getSupportedServiceNames()
414 throw (css::uno::RuntimeException, std::exception)
416 return css::uno::Sequence<OUString>{
417 "com.sun.star.drawing.framework.ResourceId"};
420 /** When eMode is DIRECTLY then the anchor of the called object and the
421 anchor represented by the given sequence of anchor URLs have to be
422 identical. When eMode is RECURSIVE then the anchor of the called
423 object has to start with the given anchor URLs.
425 bool ResourceId::IsBoundToAnchor (
426 const OUString* psFirstAnchorURL,
427 const Sequence<OUString>* paAnchorURLs,
428 AnchorBindingMode eMode) const
430 const sal_uInt32 nLocalAnchorURLCount (maResourceURLs.size() - 1);
431 const bool bHasFirstAnchorURL (psFirstAnchorURL!=NULL);
432 const sal_uInt32 nAnchorURLCount ((bHasFirstAnchorURL?1:0)
433 + (paAnchorURLs!=NULL ? paAnchorURLs->getLength() : 0));
435 // Check the lengths.
436 if (nLocalAnchorURLCount<nAnchorURLCount ||
437 (eMode==AnchorBindingMode_DIRECT && nLocalAnchorURLCount!=nAnchorURLCount))
439 return false;
442 // Compare the nAnchorURLCount bottom-most anchor URLs of this resource
443 // id and the given anchor.
444 sal_uInt32 nOffset = 0;
445 if (paAnchorURLs != NULL)
447 sal_uInt32 nCount = paAnchorURLs->getLength();
448 while (nOffset < nCount)
450 if ( ! maResourceURLs[nLocalAnchorURLCount - nOffset].equals(
451 (*paAnchorURLs)[nCount - 1 - nOffset]))
453 return false;
455 ++nOffset;
458 if (bHasFirstAnchorURL)
460 if ( ! psFirstAnchorURL->equals(maResourceURLs[nLocalAnchorURLCount - nOffset]))
461 return false;
464 return true;
467 bool ResourceId::IsBoundToAnchor (
468 const ::std::vector<OUString>& rAnchorURLs,
469 AnchorBindingMode eMode) const
471 const sal_uInt32 nLocalAnchorURLCount (maResourceURLs.size() - 1);
472 const sal_uInt32 nAnchorURLCount (rAnchorURLs.size());
474 // Check the lengths.
475 if (nLocalAnchorURLCount<nAnchorURLCount ||
476 (eMode==AnchorBindingMode_DIRECT && nLocalAnchorURLCount!=nAnchorURLCount))
478 return false;
481 // Compare the nAnchorURLCount bottom-most anchor URLs of this resource
482 // id and the given anchor.
483 for (sal_uInt32 nOffset=0; nOffset<nAnchorURLCount; ++nOffset)
485 if ( ! maResourceURLs[nLocalAnchorURLCount - nOffset].equals(
486 rAnchorURLs[nAnchorURLCount - 1 - nOffset]))
488 return false;
492 return true;
495 void ResourceId::ParseResourceURL()
497 ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex());
498 Reference<util::XURLTransformer> xURLTransformer (mxURLTransformerWeak);
499 if ( ! xURLTransformer.is())
501 // Create the URL transformer.
502 Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext());
503 xURLTransformer = Reference<util::XURLTransformer>(util::URLTransformer::create(xContext));
504 mxURLTransformerWeak = xURLTransformer;
505 SdGlobalResourceContainer::Instance().AddResource(
506 Reference<XInterface>(xURLTransformer,UNO_QUERY));
509 if (xURLTransformer.is() && !maResourceURLs.empty() )
511 mpURL.reset(new util::URL);
512 mpURL->Complete = maResourceURLs[0];
513 xURLTransformer->parseStrict(*mpURL);
514 if (mpURL->Main == maResourceURLs[0])
515 mpURL.reset();
516 else
517 maResourceURLs[0] = mpURL->Main;
521 } } // end of namespace sd::framework
524 extern "C" SAL_DLLPUBLIC_EXPORT ::com::sun::star::uno::XInterface* SAL_CALL
525 com_sun_star_comp_Draw_framework_ResourceID_get_implementation(::com::sun::star::uno::XComponentContext*,
526 ::com::sun::star::uno::Sequence<css::uno::Any> const &)
528 return cppu::acquire(new sd::framework::ResourceId());
533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */