1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ResourceId.cxx,v $
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
53 #define USE_OPTIMIZATIONS
55 namespace sd
{ namespace framework
{
57 Reference
<XInterface
> SAL_CALL
ResourceId_createInstance (
58 const Reference
<XComponentContext
>& 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(),
101 ResourceId::ResourceId (
102 const std::vector
<OUString
>& rResourceURLs
)
103 : ResourceIdInterfaceBase(),
104 maResourceURLs(rResourceURLs
),
113 ResourceId::ResourceId (
114 const OUString
& rsResourceURL
)
115 : ResourceIdInterfaceBase(),
116 maResourceURLs(1, rsResourceURL
),
119 // Handle the special case of an empty resource URL.
120 if (rsResourceURL
.getLength() == 0)
121 maResourceURLs
.clear();
128 ResourceId::ResourceId (
129 const OUString
& rsResourceURL
,
130 const OUString
& rsAnchorURL
)
131 : ResourceIdInterfaceBase(),
135 maResourceURLs
[0] = rsResourceURL
;
136 maResourceURLs
[1] = rsAnchorURL
;
143 ResourceId::ResourceId (
144 const OUString
& rsResourceURL
,
145 const ::std::vector
<OUString
>& rAnchorURLs
)
146 : ResourceIdInterfaceBase(),
147 maResourceURLs(1+rAnchorURLs
.size()),
150 maResourceURLs
[0] = rsResourceURL
;
151 for (sal_uInt32 nIndex
=0; nIndex
<rAnchorURLs
.size(); ++nIndex
)
152 maResourceURLs
[nIndex
+1] = rAnchorURLs
[nIndex
];
159 ResourceId::ResourceId (
160 const OUString
& rsResourceURL
,
161 const OUString
& rsFirstAnchorURL
,
162 const Sequence
<OUString
>& rAnchorURLs
)
163 : ResourceIdInterfaceBase(),
164 maResourceURLs(2+rAnchorURLs
.getLength()),
167 maResourceURLs
[0] = rsResourceURL
;
168 maResourceURLs
[1] = rsFirstAnchorURL
;
169 for (sal_Int32 nIndex
=0; nIndex
<rAnchorURLs
.getLength(); ++nIndex
)
170 maResourceURLs
[nIndex
+2] = rAnchorURLs
[nIndex
];
177 ResourceId::~ResourceId (void)
186 ResourceId::getResourceURL (void)
187 throw(com::sun::star::uno::RuntimeException
)
189 if (maResourceURLs
.size() > 0)
190 return maResourceURLs
[0];
199 ResourceId::getFullResourceURL (void)
200 throw(com::sun::star::uno::RuntimeException
)
202 if (mpURL
.get() != NULL
)
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
);
215 if (maResourceURLs
.size() > 0)
216 aURL
.Complete
= maResourceURLs
[0];
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];
264 return Sequence
<OUString
>();
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));
282 nPrefixEnd
= rsResourceURL
.indexOf(sal_Unicode('/'), nPrefixEnd
+1) + 1;
286 return rsResourceURL
.copy(0,nPrefixEnd
);
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)
311 ResourceId
* pId
= NULL
;
312 #ifdef USE_OPTIMIZATIONS
313 pId
= dynamic_cast<ResourceId
*>(rxResourceId
.get());
317 // We have direct access to the implementation of the given
318 // resource id object.
319 nResult
= CompareToLocalImplementation(*pId
);
323 // We have to do the comparison via the UNO interface of the
324 // given resource id object.
325 nResult
= CompareToExternalImplementation(rxResourceId
);
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)
362 // No difference found yet. When the lengths are the same then the
363 // two resource ids are equivalent. Otherwise the shorter comes
365 if (nLocalURLCount
!= nURLCount
)
367 if (nLocalURLCount
< nURLCount
)
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
)
395 nLocalResult
= maResourceURLs
[nIndex
].compareTo(rxId
->getResourceURL());
397 nLocalResult
= maResourceURLs
[nIndex
].compareTo(aAnchorURLs
[nIndex
-1]);
398 if (nLocalResult
!= 0)
400 if (nLocalResult
< 0)
410 // No difference found yet. When the lengths are the same then the
411 // two resource ids are equivalent. Otherwise the shorter comes
413 if (nLocalURLCount
!= nURLCount
)
415 if (nLocalURLCount
< nURLCount
)
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());
446 return IsBoundToAnchor(pId
->maResourceURLs
, eMode
);
450 const OUString
sResourceURL (rxResourceId
->getResourceURL());
451 const Sequence
<OUString
> aAnchorURLs (rxResourceId
->getAnchorURLs());
452 return IsBoundToAnchor(&sResourceURL
, &aAnchorURLs
, eMode
);
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
);
494 Reference
<XResourceId
> xAnchor
;
495 if (aArguments
[nIndex
] >>= xAnchor
)
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
]);
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
))
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
]))
555 if (bHasFirstAnchorURL
)
557 if ( ! psFirstAnchorURL
->equals(maResourceURLs
[nLocalAnchorURLCount
- nOffset
]))
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
))
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
]))
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"))),
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])
635 maResourceURLs
[0] = mpURL
->Main
;
640 } } // end of namespace sd::framework