merge the formfield patch from ooo-build
[ooovba.git] / sd / source / ui / framework / configuration / ResourceId.cxx
blobee568f8929f25c469e3322d6440360f5c4daffc6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ResourceId.cxx,v $
10 * $Revision: 1.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "precompiled_sd.hxx"
33 #include "framework/ResourceId.hxx"
34 #include "framework/FrameworkHelper.hxx"
35 #include "tools/SdGlobalResourceContainer.hxx"
36 #include <com/sun/star/lang/IllegalArgumentException.hpp>
37 #include <com/sun/star/uno/XComponentContext.hpp>
38 #include <comphelper/processfactory.hxx>
39 #include <rtl/ref.hxx>
41 using namespace ::com::sun::star;
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::lang;
44 using namespace ::com::sun::star::drawing::framework;
45 using ::rtl::OUString;
47 /** When the USE_OPTIMIZATIONS symbol is defined then at some optimizations
48 are activated that work only together with XResourceId objects that are
49 implemented by the ResourceId class. For other implementations of when
50 the USE_OPTIMIZATIONS symbol is not defined then alternative code is
51 used instead.
53 #define USE_OPTIMIZATIONS
55 namespace sd { namespace framework {
57 Reference<XInterface> SAL_CALL ResourceId_createInstance (
58 const Reference<XComponentContext>& rxContext)
60 (void)rxContext;
61 return Reference<XInterface>(static_cast<XWeak*>(new ::sd::framework::ResourceId()));
67 ::rtl::OUString ResourceId_getImplementationName (void) throw(RuntimeException)
69 return ::rtl::OUString(
70 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.framework.ResourceId"));
76 Sequence<rtl::OUString> SAL_CALL ResourceId_getSupportedServiceNames (void)
77 throw (RuntimeException)
79 static const ::rtl::OUString sServiceName(
80 ::rtl::OUString::createFromAscii("com.sun.star.drawing.framework.ResourceId"));
81 return Sequence<rtl::OUString>(&sServiceName, 1);
87 //===== ResourceId ============================================================
89 WeakReference<util::XURLTransformer> ResourceId::mxURLTransformerWeak;
91 ResourceId::ResourceId (void)
92 : ResourceIdInterfaceBase(),
93 maResourceURLs(0),
94 mpURL()
101 ResourceId::ResourceId (
102 const std::vector<OUString>& rResourceURLs)
103 : ResourceIdInterfaceBase(),
104 maResourceURLs(rResourceURLs),
105 mpURL()
107 ParseResourceURL();
113 ResourceId::ResourceId (
114 const OUString& rsResourceURL)
115 : ResourceIdInterfaceBase(),
116 maResourceURLs(1, rsResourceURL),
117 mpURL()
119 // Handle the special case of an empty resource URL.
120 if (rsResourceURL.getLength() == 0)
121 maResourceURLs.clear();
122 ParseResourceURL();
128 ResourceId::ResourceId (
129 const OUString& rsResourceURL,
130 const OUString& rsAnchorURL)
131 : ResourceIdInterfaceBase(),
132 maResourceURLs(2),
133 mpURL()
135 maResourceURLs[0] = rsResourceURL;
136 maResourceURLs[1] = rsAnchorURL;
137 ParseResourceURL();
143 ResourceId::ResourceId (
144 const OUString& rsResourceURL,
145 const ::std::vector<OUString>& rAnchorURLs)
146 : ResourceIdInterfaceBase(),
147 maResourceURLs(1+rAnchorURLs.size()),
148 mpURL()
150 maResourceURLs[0] = rsResourceURL;
151 for (sal_uInt32 nIndex=0; nIndex<rAnchorURLs.size(); ++nIndex)
152 maResourceURLs[nIndex+1] = rAnchorURLs[nIndex];
153 ParseResourceURL();
159 ResourceId::ResourceId (
160 const OUString& rsResourceURL,
161 const OUString& rsFirstAnchorURL,
162 const Sequence<OUString>& rAnchorURLs)
163 : ResourceIdInterfaceBase(),
164 maResourceURLs(2+rAnchorURLs.getLength()),
165 mpURL()
167 maResourceURLs[0] = rsResourceURL;
168 maResourceURLs[1] = rsFirstAnchorURL;
169 for (sal_Int32 nIndex=0; nIndex<rAnchorURLs.getLength(); ++nIndex)
170 maResourceURLs[nIndex+2] = rAnchorURLs[nIndex];
171 ParseResourceURL();
177 ResourceId::~ResourceId (void)
179 mpURL.reset();
185 OUString SAL_CALL
186 ResourceId::getResourceURL (void)
187 throw(com::sun::star::uno::RuntimeException)
189 if (maResourceURLs.size() > 0)
190 return maResourceURLs[0];
191 else
192 return OUString();
198 util::URL SAL_CALL
199 ResourceId::getFullResourceURL (void)
200 throw(com::sun::star::uno::RuntimeException)
202 if (mpURL.get() != NULL)
203 return *mpURL;
205 Reference<util::XURLTransformer> xURLTransformer (mxURLTransformerWeak);
206 if (xURLTransformer.is() && maResourceURLs.size() > 0)
208 mpURL.reset(new util::URL);
209 mpURL->Complete = maResourceURLs[0];
210 xURLTransformer->parseStrict(*mpURL);
211 return *mpURL;
214 util::URL aURL;
215 if (maResourceURLs.size() > 0)
216 aURL.Complete = maResourceURLs[0];
217 return aURL;
223 sal_Bool SAL_CALL
224 ResourceId::hasAnchor (void)
225 throw (RuntimeException)
227 return maResourceURLs.size()>1;
233 Reference<XResourceId> SAL_CALL
234 ResourceId::getAnchor (void)
235 throw (RuntimeException)
237 ::rtl::Reference<ResourceId> rResourceId (new ResourceId());
238 const sal_Int32 nAnchorCount (maResourceURLs.size()-1);
239 if (nAnchorCount > 0)
241 rResourceId->maResourceURLs.resize(nAnchorCount);
242 for (sal_Int32 nIndex=0; nIndex<nAnchorCount; ++nIndex)
243 rResourceId->maResourceURLs[nIndex] = maResourceURLs[nIndex+1];
245 return Reference<XResourceId>(rResourceId.get());
251 Sequence<OUString> SAL_CALL
252 ResourceId::getAnchorURLs (void)
253 throw (RuntimeException)
255 const sal_Int32 nAnchorCount (maResourceURLs.size() - 1);
256 if (nAnchorCount > 0)
258 Sequence<OUString> aAnchorURLs (nAnchorCount);
259 for (sal_Int32 nIndex=0; nIndex<nAnchorCount; ++nIndex)
260 aAnchorURLs[nIndex] = maResourceURLs[nIndex+1];
261 return aAnchorURLs;
263 else
264 return Sequence<OUString>();
270 OUString SAL_CALL
271 ResourceId::getResourceTypePrefix (void)
272 throw (RuntimeException)
274 if (maResourceURLs.size() > 0)
276 // Return the "private:resource/<type>/" prefix.
278 // Get the the prefix that ends with the second "/".
279 const OUString& rsResourceURL (maResourceURLs[0]);
280 sal_Int32 nPrefixEnd (rsResourceURL.indexOf(sal_Unicode('/'), 0));
281 if (nPrefixEnd >= 0)
282 nPrefixEnd = rsResourceURL.indexOf(sal_Unicode('/'), nPrefixEnd+1) + 1;
283 else
284 nPrefixEnd = 0;
286 return rsResourceURL.copy(0,nPrefixEnd);
288 else
289 return OUString();
295 sal_Int16 SAL_CALL
296 ResourceId::compareTo (const Reference<XResourceId>& rxResourceId)
297 throw (RuntimeException)
299 sal_Int16 nResult (0);
301 if ( ! rxResourceId.is())
303 // The empty reference is interpreted as empty resource id object.
304 if (maResourceURLs.size() > 0)
305 nResult = +1;
306 else
307 nResult = 0;
309 else
311 ResourceId* pId = NULL;
312 #ifdef USE_OPTIMIZATIONS
313 pId = dynamic_cast<ResourceId*>(rxResourceId.get());
314 #endif
315 if (pId != NULL)
317 // We have direct access to the implementation of the given
318 // resource id object.
319 nResult = CompareToLocalImplementation(*pId);
321 else
323 // We have to do the comparison via the UNO interface of the
324 // given resource id object.
325 nResult = CompareToExternalImplementation(rxResourceId);
329 return nResult;
335 sal_Int16 ResourceId::CompareToLocalImplementation (const ResourceId& rId) const
337 sal_Int16 nResult (0);
339 const sal_uInt32 nLocalURLCount (maResourceURLs.size());
340 const sal_uInt32 nURLCount(rId.maResourceURLs.size());
342 // Start comparison with the top most anchors.
343 for (sal_Int32 nIndex=nURLCount-1,nLocalIndex=nLocalURLCount-1;
344 nIndex>=0 && nLocalIndex>=0;
345 --nIndex,--nLocalIndex)
347 const OUString sLocalURL (maResourceURLs[nLocalIndex]);
348 const OUString sURL (rId.maResourceURLs[nIndex]);
349 const sal_Int32 nLocalResult (sURL.compareTo(sLocalURL));
350 if (nLocalResult != 0)
352 if (nLocalResult < 0)
353 nResult = -1;
354 else
355 nResult = +1;
356 break;
360 if (nResult == 0)
362 // No difference found yet. When the lengths are the same then the
363 // two resource ids are equivalent. Otherwise the shorter comes
364 // first.
365 if (nLocalURLCount != nURLCount)
367 if (nLocalURLCount < nURLCount)
368 nResult = -1;
369 else
370 nResult = +1;
374 return nResult;
380 sal_Int16 ResourceId::CompareToExternalImplementation (const Reference<XResourceId>& rxId) const
382 sal_Int16 nResult (0);
384 const Sequence<OUString> aAnchorURLs (rxId->getAnchorURLs());
385 const sal_uInt32 nLocalURLCount (maResourceURLs.size());
386 const sal_uInt32 nURLCount(1+aAnchorURLs.getLength());
388 // Start comparison with the top most anchors.
389 sal_Int32 nLocalResult (0);
390 for (sal_Int32 nIndex=nURLCount-1,nLocalIndex=nLocalURLCount-1;
391 nIndex>=0&&nLocalIndex>=0;
392 --nIndex,--nLocalIndex)
394 if (nIndex == 0 )
395 nLocalResult = maResourceURLs[nIndex].compareTo(rxId->getResourceURL());
396 else
397 nLocalResult = maResourceURLs[nIndex].compareTo(aAnchorURLs[nIndex-1]);
398 if (nLocalResult != 0)
400 if (nLocalResult < 0)
401 nResult = -1;
402 else
403 nResult = +1;
404 break;
408 if (nResult == 0)
410 // No difference found yet. When the lengths are the same then the
411 // two resource ids are equivalent. Otherwise the shorter comes
412 // first.
413 if (nLocalURLCount != nURLCount)
415 if (nLocalURLCount < nURLCount)
416 nResult = -1;
417 else
418 nResult = +1;
422 return nResult;
428 sal_Bool SAL_CALL
429 ResourceId::isBoundTo (
430 const Reference<XResourceId>& rxResourceId,
431 AnchorBindingMode eMode)
432 throw (RuntimeException)
434 if ( ! rxResourceId.is())
436 // An empty reference is interpreted as empty resource id.
437 return IsBoundToAnchor(NULL, NULL, eMode);
440 ResourceId* pId = NULL;
441 #ifdef USE_OPTIMIZATIONS
442 pId = dynamic_cast<ResourceId*>(rxResourceId.get());
443 #endif
444 if (pId != NULL)
446 return IsBoundToAnchor(pId->maResourceURLs, eMode);
448 else
450 const OUString sResourceURL (rxResourceId->getResourceURL());
451 const Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs());
452 return IsBoundToAnchor(&sResourceURL, &aAnchorURLs, eMode);
459 sal_Bool SAL_CALL
460 ResourceId::isBoundToURL (
461 const OUString& rsAnchorURL,
462 AnchorBindingMode eMode)
463 throw (RuntimeException)
465 return IsBoundToAnchor(&rsAnchorURL, NULL, eMode);
471 Reference<XResourceId> SAL_CALL
472 ResourceId::clone (void)
473 throw(RuntimeException)
475 return new ResourceId(maResourceURLs);
481 //----- XInitialization -------------------------------------------------------
483 void SAL_CALL ResourceId::initialize (const Sequence<Any>& aArguments)
484 throw (RuntimeException)
486 sal_uInt32 nCount (aArguments.getLength());
487 for (sal_uInt32 nIndex=0; nIndex<nCount; ++nIndex)
489 OUString sResourceURL;
490 if (aArguments[nIndex] >>= sResourceURL)
491 maResourceURLs.push_back(sResourceURL);
492 else
494 Reference<XResourceId> xAnchor;
495 if (aArguments[nIndex] >>= xAnchor)
497 if (xAnchor.is())
499 maResourceURLs.push_back(xAnchor->getResourceURL());
500 Sequence<OUString> aAnchorURLs (xAnchor->getAnchorURLs());
501 for (sal_Int32 nURLIndex=0; nURLIndex<aAnchorURLs.getLength(); ++nURLIndex)
503 maResourceURLs.push_back(aAnchorURLs[nURLIndex]);
509 ParseResourceURL();
515 //-----------------------------------------------------------------------------
517 /** When eMode is DIRECTLY then the anchor of the called object and the
518 anchor represented by the given sequence of anchor URLs have to be
519 identical. When eMode is RECURSIVE then the anchor of the called
520 object has to start with the given anchor URLs.
522 bool ResourceId::IsBoundToAnchor (
523 const OUString* psFirstAnchorURL,
524 const Sequence<OUString>* paAnchorURLs,
525 AnchorBindingMode eMode) const
527 const sal_uInt32 nLocalAnchorURLCount (maResourceURLs.size() - 1);
528 const bool bHasFirstAnchorURL (psFirstAnchorURL!=NULL);
529 const sal_uInt32 nAnchorURLCount ((bHasFirstAnchorURL?1:0)
530 + (paAnchorURLs!=NULL ? paAnchorURLs->getLength() : 0));
532 // Check the lengths.
533 if (nLocalAnchorURLCount<nAnchorURLCount ||
534 (eMode==AnchorBindingMode_DIRECT && nLocalAnchorURLCount!=nAnchorURLCount))
536 return false;
539 // Compare the nAnchorURLCount bottom-most anchor URLs of this resource
540 // id and the given anchor.
541 sal_uInt32 nOffset = 0;
542 if (paAnchorURLs != NULL)
544 sal_uInt32 nCount = paAnchorURLs->getLength();
545 while (nOffset < nCount)
547 if ( ! maResourceURLs[nLocalAnchorURLCount - nOffset].equals(
548 (*paAnchorURLs)[nCount - 1 - nOffset]))
550 return false;
552 ++nOffset;
555 if (bHasFirstAnchorURL)
557 if ( ! psFirstAnchorURL->equals(maResourceURLs[nLocalAnchorURLCount - nOffset]))
558 return false;
561 return true;
567 bool ResourceId::IsBoundToAnchor (
568 const ::std::vector<OUString>& rAnchorURLs,
569 AnchorBindingMode eMode) const
571 const sal_uInt32 nLocalAnchorURLCount (maResourceURLs.size() - 1);
572 const sal_uInt32 nAnchorURLCount (rAnchorURLs.size());
574 // Check the lengths.
575 if (nLocalAnchorURLCount<nAnchorURLCount ||
576 (eMode==AnchorBindingMode_DIRECT && nLocalAnchorURLCount!=nAnchorURLCount))
578 return false;
581 // Compare the nAnchorURLCount bottom-most anchor URLs of this resource
582 // id and the given anchor.
583 for (sal_uInt32 nOffset=0; nOffset<nAnchorURLCount; ++nOffset)
585 if ( ! maResourceURLs[nLocalAnchorURLCount - nOffset].equals(
586 rAnchorURLs[nAnchorURLCount - 1 - nOffset]))
588 return false;
592 return true;
598 bool ResourceId::IsValid (void) const
600 return maResourceURLs.size() == 0
601 || maResourceURLs[0].getLength()>0
602 || maResourceURLs.size() == 1;
609 void ResourceId::ParseResourceURL (void)
611 ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex());
612 Reference<util::XURLTransformer> xURLTransformer (mxURLTransformerWeak);
613 if ( ! xURLTransformer.is())
615 // Create the URL transformer.
616 Reference<lang::XMultiServiceFactory> xServiceManager (
617 ::comphelper::getProcessServiceFactory());
618 xURLTransformer = Reference<util::XURLTransformer>(
619 xServiceManager->createInstance(
620 OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))),
621 UNO_QUERY);
622 mxURLTransformerWeak = xURLTransformer;
623 SdGlobalResourceContainer::Instance().AddResource(
624 Reference<XInterface>(xURLTransformer,UNO_QUERY));
627 if (xURLTransformer.is() && maResourceURLs.size() > 0)
629 mpURL.reset(new util::URL);
630 mpURL->Complete = maResourceURLs[0];
631 xURLTransformer->parseStrict(*mpURL);
632 if (mpURL->Main == maResourceURLs[0])
633 mpURL.reset();
634 else
635 maResourceURLs[0] = mpURL->Main;
640 } } // end of namespace sd::framework