LibreOffice Module sd (master) 1
ResourceId.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
22#include <com/sun/star/util/URLTransformer.hpp>
26#include <rtl/ref.hxx>
27
28#include <algorithm>
29
30namespace com::sun::star::uno { class XComponentContext; }
31
32using namespace ::com::sun::star;
33using namespace ::com::sun::star::uno;
34using namespace ::com::sun::star::lang;
36
43#define USE_OPTIMIZATIONS
44
45namespace sd::framework {
46
47//===== ResourceId ============================================================
48
49WeakReference<util::XURLTransformer> ResourceId::mxURLTransformerWeak;
50
52 : maResourceURLs(0)
53{
54}
55
57 std::vector<OUString>&& rResourceURLs)
58 : maResourceURLs(std::move(rResourceURLs))
59{
61}
62
64 const OUString& rsResourceURL)
65 : maResourceURLs(1, rsResourceURL)
66{
67 // Handle the special case of an empty resource URL.
68 if (rsResourceURL.isEmpty())
69 maResourceURLs.clear();
71}
72
74 const OUString& rsResourceURL,
75 const OUString& rsAnchorURL)
76 : maResourceURLs(2)
77{
78 maResourceURLs[0] = rsResourceURL;
79 maResourceURLs[1] = rsAnchorURL;
81}
82
84 const OUString& rsResourceURL,
85 const OUString& rsFirstAnchorURL,
86 const Sequence<OUString>& rAnchorURLs)
87 : maResourceURLs(2+rAnchorURLs.getLength())
88{
89 maResourceURLs[0] = rsResourceURL;
90 maResourceURLs[1] = rsFirstAnchorURL;
91 std::copy(rAnchorURLs.begin(), rAnchorURLs.end(), std::next(maResourceURLs.begin(), 2));
93}
94
96{
97 mpURL.reset();
98}
99
100OUString SAL_CALL
102{
103 if (!maResourceURLs.empty())
104 return maResourceURLs[0];
105 else
106 return OUString();
107}
108
109util::URL SAL_CALL
111{
112 if (mpURL != nullptr)
113 return *mpURL;
114
115 Reference<util::XURLTransformer> xURLTransformer (mxURLTransformerWeak);
116 if (xURLTransformer.is() && !maResourceURLs.empty() )
117 {
118 mpURL.reset(new util::URL);
119 mpURL->Complete = maResourceURLs[0];
120 xURLTransformer->parseStrict(*mpURL);
121 return *mpURL;
122 }
123
124 util::URL aURL;
125 if (!maResourceURLs.empty())
126 aURL.Complete = maResourceURLs[0];
127 return aURL;
128}
129
130sal_Bool SAL_CALL
132{
133 return maResourceURLs.size()>1;
134}
135
136Reference<XResourceId> SAL_CALL
138{
139 ::rtl::Reference<ResourceId> rResourceId (new ResourceId());
140 const sal_Int32 nAnchorCount (maResourceURLs.size()-1);
141 if (nAnchorCount > 0)
142 {
143 rResourceId->maResourceURLs.resize(nAnchorCount);
144 for (sal_Int32 nIndex=0; nIndex<nAnchorCount; ++nIndex)
145 rResourceId->maResourceURLs[nIndex] = maResourceURLs[nIndex+1];
146 }
147 return rResourceId;
148}
149
150Sequence<OUString> SAL_CALL
152{
153 const sal_Int32 nAnchorCount (maResourceURLs.size() - 1);
154 if (nAnchorCount > 0)
155 {
156 Sequence<OUString> aAnchorURLs (nAnchorCount);
157 std::copy_n(maResourceURLs.begin() + 1, nAnchorCount, aAnchorURLs.getArray());
158 return aAnchorURLs;
159 }
160 else
161 return Sequence<OUString>();
162}
163
164OUString SAL_CALL
166{
167 if (!maResourceURLs.empty() )
168 {
169 // Return the "private:resource/<type>/" prefix.
170
171 // Get the prefix that ends with the second "/".
172 const OUString& rsResourceURL (maResourceURLs[0]);
173 sal_Int32 nPrefixEnd (rsResourceURL.indexOf('/'));
174 if (nPrefixEnd >= 0)
175 nPrefixEnd = rsResourceURL.indexOf('/', nPrefixEnd+1) + 1;
176 else
177 nPrefixEnd = 0;
178
179 return rsResourceURL.copy(0,nPrefixEnd);
180 }
181 else
182 return OUString();
183}
184
185sal_Int16 SAL_CALL
186 ResourceId::compareTo (const Reference<XResourceId>& rxResourceId)
187{
188 sal_Int16 nResult (0);
189
190 if ( ! rxResourceId.is())
191 {
192 // The empty reference is interpreted as empty resource id object.
193 if (!maResourceURLs.empty())
194 nResult = +1;
195 else
196 nResult = 0;
197 }
198 else
199 {
200 ResourceId* pId = nullptr;
201#ifdef USE_OPTIMIZATIONS
202 pId = dynamic_cast<ResourceId*>(rxResourceId.get());
203#endif
204 if (pId != nullptr)
205 {
206 // We have direct access to the implementation of the given
207 // resource id object.
208 nResult = CompareToLocalImplementation(*pId);
209 }
210 else
211 {
212 // We have to do the comparison via the UNO interface of the
213 // given resource id object.
214 nResult = CompareToExternalImplementation(rxResourceId);
215 }
216 }
217
218 return nResult;
219}
220
222{
223 sal_Int16 nResult (0);
224
225 const sal_uInt32 nLocalURLCount (maResourceURLs.size());
226 const sal_uInt32 nURLCount(rId.maResourceURLs.size());
227
228 // Start comparison with the top most anchors.
229 for (sal_Int32 nIndex=nURLCount-1,nLocalIndex=nLocalURLCount-1;
230 nIndex>=0 && nLocalIndex>=0;
231 --nIndex,--nLocalIndex)
232 {
233 const OUString sLocalURL (maResourceURLs[nLocalIndex]);
234 const OUString sURL (rId.maResourceURLs[nIndex]);
235 const sal_Int32 nLocalResult (sURL.compareTo(sLocalURL));
236 if (nLocalResult != 0)
237 {
238 if (nLocalResult < 0)
239 nResult = -1;
240 else
241 nResult = +1;
242 break;
243 }
244 }
245
246 if (nResult == 0)
247 {
248 // No difference found yet. When the lengths are the same then the
249 // two resource ids are equivalent. Otherwise the shorter comes
250 // first.
251 if (nLocalURLCount != nURLCount)
252 {
253 if (nLocalURLCount < nURLCount)
254 nResult = -1;
255 else
256 nResult = +1;
257 }
258 }
259
260 return nResult;
261}
262
263sal_Int16 ResourceId::CompareToExternalImplementation (const Reference<XResourceId>& rxId) const
264{
265 sal_Int16 nResult (0);
266
267 const Sequence<OUString> aAnchorURLs (rxId->getAnchorURLs());
268 const sal_uInt32 nLocalURLCount (maResourceURLs.size());
269 const sal_uInt32 nURLCount(1+aAnchorURLs.getLength());
270
271 // Start comparison with the top most anchors.
272 sal_Int32 nLocalResult (0);
273 for (sal_Int32 nIndex=nURLCount-1,nLocalIndex=nLocalURLCount-1;
274 nIndex>=0&&nLocalIndex>=0;
275 --nIndex,--nLocalIndex)
276 {
277 if (nIndex == 0 )
278 nLocalResult = maResourceURLs[nIndex].compareTo(rxId->getResourceURL());
279 else
280 nLocalResult = maResourceURLs[nIndex].compareTo(aAnchorURLs[nIndex-1]);
281 if (nLocalResult != 0)
282 {
283 if (nLocalResult < 0)
284 nResult = -1;
285 else
286 nResult = +1;
287 break;
288 }
289 }
290
291 if (nResult == 0)
292 {
293 // No difference found yet. When the lengths are the same then the
294 // two resource ids are equivalent. Otherwise the shorter comes
295 // first.
296 if (nLocalURLCount != nURLCount)
297 {
298 if (nLocalURLCount < nURLCount)
299 nResult = -1;
300 else
301 nResult = +1;
302 }
303 }
304
305 return nResult;
306}
307
308sal_Bool SAL_CALL
310 const Reference<XResourceId>& rxResourceId,
311 AnchorBindingMode eMode)
312{
313 if ( ! rxResourceId.is())
314 {
315 // An empty reference is interpreted as empty resource id.
316 return IsBoundToAnchor(nullptr, nullptr, eMode);
317 }
318
319 ResourceId* pId = nullptr;
320#ifdef USE_OPTIMIZATIONS
321 pId = dynamic_cast<ResourceId*>(rxResourceId.get());
322#endif
323 if (pId != nullptr)
324 {
326 }
327 else
328 {
329 const OUString sResourceURL (rxResourceId->getResourceURL());
330 const Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs());
331 return IsBoundToAnchor(&sResourceURL, &aAnchorURLs, eMode);
332 }
333}
334
335sal_Bool SAL_CALL
337 const OUString& rsAnchorURL,
338 AnchorBindingMode eMode)
339{
340 return IsBoundToAnchor(&rsAnchorURL, nullptr, eMode);
341}
342
343Reference<XResourceId> SAL_CALL
345{
346 return new ResourceId(std::vector(maResourceURLs));
347}
348
349//----- XInitialization -------------------------------------------------------
350
351void SAL_CALL ResourceId::initialize (const Sequence<Any>& aArguments)
352{
353 for (const auto& rArgument : aArguments)
354 {
355 OUString sResourceURL;
356 if (rArgument >>= sResourceURL)
357 maResourceURLs.push_back(sResourceURL);
358 else
359 {
360 Reference<XResourceId> xAnchor;
361 if (rArgument >>= xAnchor)
362 {
363 if (xAnchor.is())
364 {
365 maResourceURLs.push_back(xAnchor->getResourceURL());
366 const Sequence<OUString> aAnchorURLs (xAnchor->getAnchorURLs());
367 maResourceURLs.insert( maResourceURLs.end(), aAnchorURLs.begin(), aAnchorURLs.end() );
368 }
369 }
370 }
371 }
373}
374
376{
377 return "com.sun.star.comp.Draw.framework.ResourceId";
378}
379
380sal_Bool ResourceId::supportsService(OUString const & ServiceName)
381{
383}
384
385css::uno::Sequence<OUString> ResourceId::getSupportedServiceNames()
386{
387 return {"com.sun.star.drawing.framework.ResourceId"};
388}
389
396 const OUString* psFirstAnchorURL,
397 const Sequence<OUString>* paAnchorURLs,
398 AnchorBindingMode eMode) const
399{
400 const sal_uInt32 nLocalAnchorURLCount (maResourceURLs.size() - 1);
401 const bool bHasFirstAnchorURL (psFirstAnchorURL!=nullptr);
402 const sal_uInt32 nAnchorURLCount ((bHasFirstAnchorURL?1:0)
403 + (paAnchorURLs!=nullptr ? paAnchorURLs->getLength() : 0));
404
405 // Check the lengths.
406 if (nLocalAnchorURLCount<nAnchorURLCount ||
407 (eMode==AnchorBindingMode_DIRECT && nLocalAnchorURLCount!=nAnchorURLCount))
408 {
409 return false;
410 }
411
412 // Compare the nAnchorURLCount bottom-most anchor URLs of this resource
413 // id and the given anchor.
414 sal_uInt32 nOffset = 0;
415 if (paAnchorURLs != nullptr)
416 {
417 sal_uInt32 nCount = paAnchorURLs->getLength();
418 while (nOffset < nCount)
419 {
420 if ( maResourceURLs[nLocalAnchorURLCount - nOffset] !=
421 (*paAnchorURLs)[nCount - 1 - nOffset] )
422 {
423 return false;
424 }
425 ++nOffset;
426 }
427 }
428 if (bHasFirstAnchorURL)
429 {
430 if ( *psFirstAnchorURL != maResourceURLs[nLocalAnchorURLCount - nOffset] )
431 return false;
432 }
433
434 return true;
435}
436
438 const ::std::vector<OUString>& rAnchorURLs,
439 AnchorBindingMode eMode) const
440{
441 const sal_uInt32 nLocalAnchorURLCount (maResourceURLs.size() - 1);
442 const sal_uInt32 nAnchorURLCount (rAnchorURLs.size());
443
444 // Check the lengths.
445 if (nLocalAnchorURLCount<nAnchorURLCount ||
446 (eMode==AnchorBindingMode_DIRECT && nLocalAnchorURLCount!=nAnchorURLCount))
447 {
448 return false;
449 }
450
451 // Compare the nAnchorURLCount bottom-most anchor URLs of this resource
452 // id and the given anchor.
453 for (sal_uInt32 nOffset=0; nOffset<nAnchorURLCount; ++nOffset)
454 {
455 if ( maResourceURLs[nLocalAnchorURLCount - nOffset] !=
456 rAnchorURLs[nAnchorURLCount - 1 - nOffset] )
457 {
458 return false;
459 }
460 }
461
462 return true;
463}
464
466{
467 ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex());
468 Reference<util::XURLTransformer> xURLTransformer (mxURLTransformerWeak);
469 if ( ! xURLTransformer.is())
470 {
471 // Create the URL transformer.
472 Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext());
473 xURLTransformer.set(util::URLTransformer::create(xContext));
474 mxURLTransformerWeak = xURLTransformer;
476 Reference<XInterface>(xURLTransformer,UNO_QUERY));
477 }
478
479 if (xURLTransformer.is() && !maResourceURLs.empty() )
480 {
481 mpURL.reset(new util::URL);
482 mpURL->Complete = maResourceURLs[0];
483 xURLTransformer->parseStrict(*mpURL);
484 if (mpURL->Main == maResourceURLs[0])
485 mpURL.reset();
486 else
487 maResourceURLs[0] = mpURL->Main;
488 }
489}
490
491} // end of namespace sd::framework
492
493
494extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
496 css::uno::Sequence<css::uno::Any> const &)
497{
498 return cppu::acquire(new sd::framework::ResourceId());
499}
500
501
502/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_Draw_framework_ResourceID_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
Definition: ResourceId.cxx:495
void AddResource(::std::unique_ptr< SdGlobalResource > pResource)
Add a resource to the container.
static SdGlobalResourceContainer & Instance()
Implementation of the css::drawing::framework::ResourceId service and the css::drawing::framework::XR...
Definition: ResourceId.hxx:50
bool IsBoundToAnchor(const OUString *psFirstAnchorURL, const css::uno::Sequence< OUString > *paAnchorURLs, css::drawing::framework::AnchorBindingMode eMode) const
Return whether the called ResourceId object is bound to the anchor consisting of the URLs given by ps...
virtual css::uno::Reference< css::drawing::framework::XResourceId > SAL_CALL clone() override
Definition: ResourceId.cxx:344
css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: ResourceId.cxx:385
virtual css::util::URL SAL_CALL getFullResourceURL() override
Definition: ResourceId.cxx:110
virtual css::uno::Sequence< OUString > SAL_CALL getAnchorURLs() override
Definition: ResourceId.cxx:151
virtual css::uno::Reference< css::drawing::framework::XResourceId > SAL_CALL getAnchor() override
Definition: ResourceId.cxx:137
std::unique_ptr< css::util::URL > mpURL
Definition: ResourceId.hxx:159
ResourceId()
Create a new, empty resource id.
Definition: ResourceId.cxx:51
virtual sal_Int16 SAL_CALL compareTo(const css::uno::Reference< css::drawing::framework::XResourceId > &rxResourceId) override
Definition: ResourceId.cxx:186
virtual OUString SAL_CALL getResourceTypePrefix() override
Definition: ResourceId.cxx:165
sal_Int16 CompareToExternalImplementation(const css::uno::Reference< css::drawing::framework::XResourceId > &rxId) const
Compare the called ResourceId object to the given XResourceId object reference.
Definition: ResourceId.cxx:263
virtual sal_Bool SAL_CALL hasAnchor() override
Definition: ResourceId.cxx:131
virtual ~ResourceId() override
Definition: ResourceId.cxx:95
sal_Bool SAL_CALL supportsService(OUString const &ServiceName) override
Definition: ResourceId.cxx:380
virtual OUString SAL_CALL getResourceURL() override
Definition: ResourceId.cxx:101
std::vector< OUString > maResourceURLs
The set of URLs that consist of the resource URL at index 0 and the anchor URLs and indices 1 and abo...
Definition: ResourceId.hxx:157
OUString SAL_CALL getImplementationName() override
Definition: ResourceId.cxx:375
static css::uno::WeakReference< css::util::XURLTransformer > mxURLTransformerWeak
Definition: ResourceId.hxx:161
sal_Int16 CompareToLocalImplementation(const ResourceId &rId) const
Compare the called ResourceId object to the given ResourceId object.
Definition: ResourceId.cxx:221
virtual sal_Bool SAL_CALL isBoundToURL(const OUString &rsAnchorURL, css::drawing::framework::AnchorBindingMode eMode) override
Definition: ResourceId.cxx:336
virtual sal_Bool SAL_CALL isBoundTo(const css::uno::Reference< css::drawing::framework::XResourceId > &rxResourceId, css::drawing::framework::AnchorBindingMode eMode) override
Definition: ResourceId.cxx:309
void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &aArguments) override
Definition: ResourceId.cxx:351
int nCount
URL aURL
Sequence< PropertyValue > aArguments
sal_Int32 nIndex
Mode eMode
double getLength(const B2DPolygon &rCandidate)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
unsigned char sal_Bool