1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
41 #define USE_OPTIMIZATIONS
43 namespace sd
{ namespace framework
{
45 Reference
<XInterface
> SAL_CALL
ResourceId_createInstance (
46 const Reference
<XComponentContext
>& 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(),
87 ResourceId::ResourceId (
88 const std::vector
<OUString
>& rResourceURLs
)
89 : ResourceIdInterfaceBase(),
90 maResourceURLs(rResourceURLs
),
99 ResourceId::ResourceId (
100 const OUString
& rsResourceURL
)
101 : ResourceIdInterfaceBase(),
102 maResourceURLs(1, rsResourceURL
),
105 // Handle the special case of an empty resource URL.
106 if (rsResourceURL
.isEmpty())
107 maResourceURLs
.clear();
114 ResourceId::ResourceId (
115 const OUString
& rsResourceURL
,
116 const OUString
& rsAnchorURL
)
117 : ResourceIdInterfaceBase(),
121 maResourceURLs
[0] = rsResourceURL
;
122 maResourceURLs
[1] = rsAnchorURL
;
129 ResourceId::ResourceId (
130 const OUString
& rsResourceURL
,
131 const ::std::vector
<OUString
>& rAnchorURLs
)
132 : ResourceIdInterfaceBase(),
133 maResourceURLs(1+rAnchorURLs
.size()),
136 maResourceURLs
[0] = rsResourceURL
;
137 for (sal_uInt32 nIndex
=0; nIndex
<rAnchorURLs
.size(); ++nIndex
)
138 maResourceURLs
[nIndex
+1] = rAnchorURLs
[nIndex
];
145 ResourceId::ResourceId (
146 const OUString
& rsResourceURL
,
147 const OUString
& rsFirstAnchorURL
,
148 const Sequence
<OUString
>& rAnchorURLs
)
149 : ResourceIdInterfaceBase(),
150 maResourceURLs(2+rAnchorURLs
.getLength()),
153 maResourceURLs
[0] = rsResourceURL
;
154 maResourceURLs
[1] = rsFirstAnchorURL
;
155 for (sal_Int32 nIndex
=0; nIndex
<rAnchorURLs
.getLength(); ++nIndex
)
156 maResourceURLs
[nIndex
+2] = rAnchorURLs
[nIndex
];
163 ResourceId::~ResourceId (void)
172 ResourceId::getResourceURL (void)
173 throw(com::sun::star::uno::RuntimeException
)
175 if (!maResourceURLs
.empty())
176 return maResourceURLs
[0];
185 ResourceId::getFullResourceURL (void)
186 throw(com::sun::star::uno::RuntimeException
)
188 if (mpURL
.get() != NULL
)
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
);
201 if (!maResourceURLs
.empty())
202 aURL
.Complete
= maResourceURLs
[0];
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];
250 return Sequence
<OUString
>();
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));
268 nPrefixEnd
= rsResourceURL
.indexOf(sal_Unicode('/'), nPrefixEnd
+1) + 1;
272 return rsResourceURL
.copy(0,nPrefixEnd
);
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())
297 ResourceId
* pId
= NULL
;
298 #ifdef USE_OPTIMIZATIONS
299 pId
= dynamic_cast<ResourceId
*>(rxResourceId
.get());
303 // We have direct access to the implementation of the given
304 // resource id object.
305 nResult
= CompareToLocalImplementation(*pId
);
309 // We have to do the comparison via the UNO interface of the
310 // given resource id object.
311 nResult
= CompareToExternalImplementation(rxResourceId
);
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)
348 // No difference found yet. When the lengths are the same then the
349 // two resource ids are equivalent. Otherwise the shorter comes
351 if (nLocalURLCount
!= nURLCount
)
353 if (nLocalURLCount
< nURLCount
)
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
)
381 nLocalResult
= maResourceURLs
[nIndex
].compareTo(rxId
->getResourceURL());
383 nLocalResult
= maResourceURLs
[nIndex
].compareTo(aAnchorURLs
[nIndex
-1]);
384 if (nLocalResult
!= 0)
386 if (nLocalResult
< 0)
396 // No difference found yet. When the lengths are the same then the
397 // two resource ids are equivalent. Otherwise the shorter comes
399 if (nLocalURLCount
!= nURLCount
)
401 if (nLocalURLCount
< nURLCount
)
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());
432 return IsBoundToAnchor(pId
->maResourceURLs
, eMode
);
436 const OUString
sResourceURL (rxResourceId
->getResourceURL());
437 const Sequence
<OUString
> aAnchorURLs (rxResourceId
->getAnchorURLs());
438 return IsBoundToAnchor(&sResourceURL
, &aAnchorURLs
, eMode
);
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
);
480 Reference
<XResourceId
> xAnchor
;
481 if (aArguments
[nIndex
] >>= xAnchor
)
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
]);
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
))
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
]))
541 if (bHasFirstAnchorURL
)
543 if ( ! psFirstAnchorURL
->equals(maResourceURLs
[nLocalAnchorURLCount
- nOffset
]))
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
))
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
]))
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])
606 maResourceURLs
[0] = mpURL
->Main
;
611 } } // end of namespace sd::framework
613 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */