bump product version to 4.1.6.2
[LibreOffice.git] / sd / source / ui / framework / configuration / ResourceId.cxx
blobfb1c771dc6872e1c6bcdaf6c2eb645fbdce8e3ef
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 .
21 #include "framework/ResourceId.hxx"
22 #include "framework/FrameworkHelper.hxx"
23 #include "tools/SdGlobalResourceContainer.hxx"
24 #include <com/sun/star/lang/IllegalArgumentException.hpp>
25 #include <com/sun/star/uno/XComponentContext.hpp>
26 #include <com/sun/star/util/URLTransformer.hpp>
27 #include <comphelper/processfactory.hxx>
28 #include <rtl/ref.hxx>
30 using namespace ::com::sun::star;
31 using namespace ::com::sun::star::uno;
32 using namespace ::com::sun::star::lang;
33 using namespace ::com::sun::star::drawing::framework;
35 /** When the USE_OPTIMIZATIONS symbol is defined then at some optimizations
36 are activated that work only together with XResourceId objects that are
37 implemented by the ResourceId class. For other implementations of when
38 the USE_OPTIMIZATIONS symbol is not defined then alternative code is
39 used instead.
41 #define USE_OPTIMIZATIONS
43 namespace sd { namespace framework {
45 Reference<XInterface> SAL_CALL ResourceId_createInstance (
46 const Reference<XComponentContext>& rxContext)
48 (void)rxContext;
49 return Reference<XInterface>(static_cast<XWeak*>(new ::sd::framework::ResourceId()));
55 OUString ResourceId_getImplementationName (void) throw(RuntimeException)
57 return OUString("com.sun.star.comp.Draw.framework.ResourceId");
63 Sequence<OUString> SAL_CALL ResourceId_getSupportedServiceNames (void)
64 throw (RuntimeException)
66 static const OUString sServiceName("com.sun.star.drawing.framework.ResourceId");
67 return Sequence<OUString>(&sServiceName, 1);
73 //===== ResourceId ============================================================
75 WeakReference<util::XURLTransformer> ResourceId::mxURLTransformerWeak;
77 ResourceId::ResourceId (void)
78 : ResourceIdInterfaceBase(),
79 maResourceURLs(0),
80 mpURL()
87 ResourceId::ResourceId (
88 const std::vector<OUString>& rResourceURLs)
89 : ResourceIdInterfaceBase(),
90 maResourceURLs(rResourceURLs),
91 mpURL()
93 ParseResourceURL();
99 ResourceId::ResourceId (
100 const OUString& rsResourceURL)
101 : ResourceIdInterfaceBase(),
102 maResourceURLs(1, rsResourceURL),
103 mpURL()
105 // Handle the special case of an empty resource URL.
106 if (rsResourceURL.isEmpty())
107 maResourceURLs.clear();
108 ParseResourceURL();
114 ResourceId::ResourceId (
115 const OUString& rsResourceURL,
116 const OUString& rsAnchorURL)
117 : ResourceIdInterfaceBase(),
118 maResourceURLs(2),
119 mpURL()
121 maResourceURLs[0] = rsResourceURL;
122 maResourceURLs[1] = rsAnchorURL;
123 ParseResourceURL();
129 ResourceId::ResourceId (
130 const OUString& rsResourceURL,
131 const ::std::vector<OUString>& rAnchorURLs)
132 : ResourceIdInterfaceBase(),
133 maResourceURLs(1+rAnchorURLs.size()),
134 mpURL()
136 maResourceURLs[0] = rsResourceURL;
137 for (sal_uInt32 nIndex=0; nIndex<rAnchorURLs.size(); ++nIndex)
138 maResourceURLs[nIndex+1] = rAnchorURLs[nIndex];
139 ParseResourceURL();
145 ResourceId::ResourceId (
146 const OUString& rsResourceURL,
147 const OUString& rsFirstAnchorURL,
148 const Sequence<OUString>& rAnchorURLs)
149 : ResourceIdInterfaceBase(),
150 maResourceURLs(2+rAnchorURLs.getLength()),
151 mpURL()
153 maResourceURLs[0] = rsResourceURL;
154 maResourceURLs[1] = rsFirstAnchorURL;
155 for (sal_Int32 nIndex=0; nIndex<rAnchorURLs.getLength(); ++nIndex)
156 maResourceURLs[nIndex+2] = rAnchorURLs[nIndex];
157 ParseResourceURL();
163 ResourceId::~ResourceId (void)
165 mpURL.reset();
171 OUString SAL_CALL
172 ResourceId::getResourceURL (void)
173 throw(com::sun::star::uno::RuntimeException)
175 if (!maResourceURLs.empty())
176 return maResourceURLs[0];
177 else
178 return OUString();
184 util::URL SAL_CALL
185 ResourceId::getFullResourceURL (void)
186 throw(com::sun::star::uno::RuntimeException)
188 if (mpURL.get() != NULL)
189 return *mpURL;
191 Reference<util::XURLTransformer> xURLTransformer (mxURLTransformerWeak);
192 if (xURLTransformer.is() && !maResourceURLs.empty() )
194 mpURL.reset(new util::URL);
195 mpURL->Complete = maResourceURLs[0];
196 xURLTransformer->parseStrict(*mpURL);
197 return *mpURL;
200 util::URL aURL;
201 if (!maResourceURLs.empty())
202 aURL.Complete = maResourceURLs[0];
203 return aURL;
209 sal_Bool SAL_CALL
210 ResourceId::hasAnchor (void)
211 throw (RuntimeException)
213 return maResourceURLs.size()>1;
219 Reference<XResourceId> SAL_CALL
220 ResourceId::getAnchor (void)
221 throw (RuntimeException)
223 ::rtl::Reference<ResourceId> rResourceId (new ResourceId());
224 const sal_Int32 nAnchorCount (maResourceURLs.size()-1);
225 if (nAnchorCount > 0)
227 rResourceId->maResourceURLs.resize(nAnchorCount);
228 for (sal_Int32 nIndex=0; nIndex<nAnchorCount; ++nIndex)
229 rResourceId->maResourceURLs[nIndex] = maResourceURLs[nIndex+1];
231 return Reference<XResourceId>(rResourceId.get());
237 Sequence<OUString> SAL_CALL
238 ResourceId::getAnchorURLs (void)
239 throw (RuntimeException)
241 const sal_Int32 nAnchorCount (maResourceURLs.size() - 1);
242 if (nAnchorCount > 0)
244 Sequence<OUString> aAnchorURLs (nAnchorCount);
245 for (sal_Int32 nIndex=0; nIndex<nAnchorCount; ++nIndex)
246 aAnchorURLs[nIndex] = maResourceURLs[nIndex+1];
247 return aAnchorURLs;
249 else
250 return Sequence<OUString>();
256 OUString SAL_CALL
257 ResourceId::getResourceTypePrefix (void)
258 throw (RuntimeException)
260 if (!maResourceURLs.empty() )
262 // Return the "private:resource/<type>/" prefix.
264 // Get the prefix that ends with the second "/".
265 const OUString& rsResourceURL (maResourceURLs[0]);
266 sal_Int32 nPrefixEnd (rsResourceURL.indexOf(sal_Unicode('/'), 0));
267 if (nPrefixEnd >= 0)
268 nPrefixEnd = rsResourceURL.indexOf(sal_Unicode('/'), nPrefixEnd+1) + 1;
269 else
270 nPrefixEnd = 0;
272 return rsResourceURL.copy(0,nPrefixEnd);
274 else
275 return OUString();
281 sal_Int16 SAL_CALL
282 ResourceId::compareTo (const Reference<XResourceId>& rxResourceId)
283 throw (RuntimeException)
285 sal_Int16 nResult (0);
287 if ( ! rxResourceId.is())
289 // The empty reference is interpreted as empty resource id object.
290 if (!maResourceURLs.empty())
291 nResult = +1;
292 else
293 nResult = 0;
295 else
297 ResourceId* pId = NULL;
298 #ifdef USE_OPTIMIZATIONS
299 pId = dynamic_cast<ResourceId*>(rxResourceId.get());
300 #endif
301 if (pId != NULL)
303 // We have direct access to the implementation of the given
304 // resource id object.
305 nResult = CompareToLocalImplementation(*pId);
307 else
309 // We have to do the comparison via the UNO interface of the
310 // given resource id object.
311 nResult = CompareToExternalImplementation(rxResourceId);
315 return nResult;
321 sal_Int16 ResourceId::CompareToLocalImplementation (const ResourceId& rId) const
323 sal_Int16 nResult (0);
325 const sal_uInt32 nLocalURLCount (maResourceURLs.size());
326 const sal_uInt32 nURLCount(rId.maResourceURLs.size());
328 // Start comparison with the top most anchors.
329 for (sal_Int32 nIndex=nURLCount-1,nLocalIndex=nLocalURLCount-1;
330 nIndex>=0 && nLocalIndex>=0;
331 --nIndex,--nLocalIndex)
333 const OUString sLocalURL (maResourceURLs[nLocalIndex]);
334 const OUString sURL (rId.maResourceURLs[nIndex]);
335 const sal_Int32 nLocalResult (sURL.compareTo(sLocalURL));
336 if (nLocalResult != 0)
338 if (nLocalResult < 0)
339 nResult = -1;
340 else
341 nResult = +1;
342 break;
346 if (nResult == 0)
348 // No difference found yet. When the lengths are the same then the
349 // two resource ids are equivalent. Otherwise the shorter comes
350 // first.
351 if (nLocalURLCount != nURLCount)
353 if (nLocalURLCount < nURLCount)
354 nResult = -1;
355 else
356 nResult = +1;
360 return nResult;
366 sal_Int16 ResourceId::CompareToExternalImplementation (const Reference<XResourceId>& rxId) const
368 sal_Int16 nResult (0);
370 const Sequence<OUString> aAnchorURLs (rxId->getAnchorURLs());
371 const sal_uInt32 nLocalURLCount (maResourceURLs.size());
372 const sal_uInt32 nURLCount(1+aAnchorURLs.getLength());
374 // Start comparison with the top most anchors.
375 sal_Int32 nLocalResult (0);
376 for (sal_Int32 nIndex=nURLCount-1,nLocalIndex=nLocalURLCount-1;
377 nIndex>=0&&nLocalIndex>=0;
378 --nIndex,--nLocalIndex)
380 if (nIndex == 0 )
381 nLocalResult = maResourceURLs[nIndex].compareTo(rxId->getResourceURL());
382 else
383 nLocalResult = maResourceURLs[nIndex].compareTo(aAnchorURLs[nIndex-1]);
384 if (nLocalResult != 0)
386 if (nLocalResult < 0)
387 nResult = -1;
388 else
389 nResult = +1;
390 break;
394 if (nResult == 0)
396 // No difference found yet. When the lengths are the same then the
397 // two resource ids are equivalent. Otherwise the shorter comes
398 // first.
399 if (nLocalURLCount != nURLCount)
401 if (nLocalURLCount < nURLCount)
402 nResult = -1;
403 else
404 nResult = +1;
408 return nResult;
414 sal_Bool SAL_CALL
415 ResourceId::isBoundTo (
416 const Reference<XResourceId>& rxResourceId,
417 AnchorBindingMode eMode)
418 throw (RuntimeException)
420 if ( ! rxResourceId.is())
422 // An empty reference is interpreted as empty resource id.
423 return IsBoundToAnchor(NULL, NULL, eMode);
426 ResourceId* pId = NULL;
427 #ifdef USE_OPTIMIZATIONS
428 pId = dynamic_cast<ResourceId*>(rxResourceId.get());
429 #endif
430 if (pId != NULL)
432 return IsBoundToAnchor(pId->maResourceURLs, eMode);
434 else
436 const OUString sResourceURL (rxResourceId->getResourceURL());
437 const Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs());
438 return IsBoundToAnchor(&sResourceURL, &aAnchorURLs, eMode);
445 sal_Bool SAL_CALL
446 ResourceId::isBoundToURL (
447 const OUString& rsAnchorURL,
448 AnchorBindingMode eMode)
449 throw (RuntimeException)
451 return IsBoundToAnchor(&rsAnchorURL, NULL, eMode);
457 Reference<XResourceId> SAL_CALL
458 ResourceId::clone (void)
459 throw(RuntimeException)
461 return new ResourceId(maResourceURLs);
467 //----- XInitialization -------------------------------------------------------
469 void SAL_CALL ResourceId::initialize (const Sequence<Any>& aArguments)
470 throw (RuntimeException)
472 sal_uInt32 nCount (aArguments.getLength());
473 for (sal_uInt32 nIndex=0; nIndex<nCount; ++nIndex)
475 OUString sResourceURL;
476 if (aArguments[nIndex] >>= sResourceURL)
477 maResourceURLs.push_back(sResourceURL);
478 else
480 Reference<XResourceId> xAnchor;
481 if (aArguments[nIndex] >>= xAnchor)
483 if (xAnchor.is())
485 maResourceURLs.push_back(xAnchor->getResourceURL());
486 Sequence<OUString> aAnchorURLs (xAnchor->getAnchorURLs());
487 for (sal_Int32 nURLIndex=0; nURLIndex<aAnchorURLs.getLength(); ++nURLIndex)
489 maResourceURLs.push_back(aAnchorURLs[nURLIndex]);
495 ParseResourceURL();
501 //-----------------------------------------------------------------------------
503 /** When eMode is DIRECTLY then the anchor of the called object and the
504 anchor represented by the given sequence of anchor URLs have to be
505 identical. When eMode is RECURSIVE then the anchor of the called
506 object has to start with the given anchor URLs.
508 bool ResourceId::IsBoundToAnchor (
509 const OUString* psFirstAnchorURL,
510 const Sequence<OUString>* paAnchorURLs,
511 AnchorBindingMode eMode) const
513 const sal_uInt32 nLocalAnchorURLCount (maResourceURLs.size() - 1);
514 const bool bHasFirstAnchorURL (psFirstAnchorURL!=NULL);
515 const sal_uInt32 nAnchorURLCount ((bHasFirstAnchorURL?1:0)
516 + (paAnchorURLs!=NULL ? paAnchorURLs->getLength() : 0));
518 // Check the lengths.
519 if (nLocalAnchorURLCount<nAnchorURLCount ||
520 (eMode==AnchorBindingMode_DIRECT && nLocalAnchorURLCount!=nAnchorURLCount))
522 return false;
525 // Compare the nAnchorURLCount bottom-most anchor URLs of this resource
526 // id and the given anchor.
527 sal_uInt32 nOffset = 0;
528 if (paAnchorURLs != NULL)
530 sal_uInt32 nCount = paAnchorURLs->getLength();
531 while (nOffset < nCount)
533 if ( ! maResourceURLs[nLocalAnchorURLCount - nOffset].equals(
534 (*paAnchorURLs)[nCount - 1 - nOffset]))
536 return false;
538 ++nOffset;
541 if (bHasFirstAnchorURL)
543 if ( ! psFirstAnchorURL->equals(maResourceURLs[nLocalAnchorURLCount - nOffset]))
544 return false;
547 return true;
553 bool ResourceId::IsBoundToAnchor (
554 const ::std::vector<OUString>& rAnchorURLs,
555 AnchorBindingMode eMode) const
557 const sal_uInt32 nLocalAnchorURLCount (maResourceURLs.size() - 1);
558 const sal_uInt32 nAnchorURLCount (rAnchorURLs.size());
560 // Check the lengths.
561 if (nLocalAnchorURLCount<nAnchorURLCount ||
562 (eMode==AnchorBindingMode_DIRECT && nLocalAnchorURLCount!=nAnchorURLCount))
564 return false;
567 // Compare the nAnchorURLCount bottom-most anchor URLs of this resource
568 // id and the given anchor.
569 for (sal_uInt32 nOffset=0; nOffset<nAnchorURLCount; ++nOffset)
571 if ( ! maResourceURLs[nLocalAnchorURLCount - nOffset].equals(
572 rAnchorURLs[nAnchorURLCount - 1 - nOffset]))
574 return false;
578 return true;
584 void ResourceId::ParseResourceURL (void)
586 ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex());
587 Reference<util::XURLTransformer> xURLTransformer (mxURLTransformerWeak);
588 if ( ! xURLTransformer.is())
590 // Create the URL transformer.
591 Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext());
592 xURLTransformer = Reference<util::XURLTransformer>(util::URLTransformer::create(xContext));
593 mxURLTransformerWeak = xURLTransformer;
594 SdGlobalResourceContainer::Instance().AddResource(
595 Reference<XInterface>(xURLTransformer,UNO_QUERY));
598 if (xURLTransformer.is() && !maResourceURLs.empty() )
600 mpURL.reset(new util::URL);
601 mpURL->Complete = maResourceURLs[0];
602 xURLTransformer->parseStrict(*mpURL);
603 if (mpURL->Main == maResourceURLs[0])
604 mpURL.reset();
605 else
606 maResourceURLs[0] = mpURL->Main;
611 } } // end of namespace sd::framework
613 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */