Line data Source code
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 :
20 : #include <com/sun/star/xml/AttributeData.hpp>
21 : #include <com/sun/star/beans/XMultiPropertySet.hpp>
22 : #include <com/sun/star/lang/IllegalArgumentException.hpp>
23 : #include <com/sun/star/lang/WrappedTargetException.hpp>
24 : #include <com/sun/star/beans/UnknownPropertyException.hpp>
25 : #include <com/sun/star/beans/PropertyVetoException.hpp>
26 : #include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
27 : #include <rtl/ustrbuf.hxx>
28 : #include <xmloff/xmlprmap.hxx>
29 : #include <xmloff/nmspmap.hxx>
30 : #include <xmloff/xmlimppr.hxx>
31 : #include <xmloff/xmlimp.hxx>
32 :
33 : #include <xmloff/unoatrcn.hxx>
34 : #include <xmloff/xmlnmspe.hxx>
35 : #include <xmloff/xmltoken.hxx>
36 : #include <xmloff/xmlerror.hxx>
37 : #include <xmloff/contextid.hxx>
38 : #include <xmloff/xmltypes.hxx>
39 : #include <xmloff/maptype.hxx>
40 :
41 : #include <algorithm>
42 : #include <functional>
43 : #include <utility>
44 : #include <vector>
45 :
46 : using namespace ::com::sun::star::uno;
47 : using namespace ::com::sun::star::beans;
48 : using namespace ::com::sun::star::container;
49 : using namespace ::com::sun::star::xml;
50 : using namespace ::com::sun::star::xml::sax;
51 :
52 : using namespace ::std;
53 : using namespace ::xmloff::token;
54 : using ::com::sun::star::lang::IllegalArgumentException;
55 : using ::com::sun::star::lang::WrappedTargetException;
56 : using ::com::sun::star::beans::UnknownPropertyException;
57 : using ::com::sun::star::beans::PropertyVetoException;
58 :
59 :
60 27190 : SvXMLImportPropertyMapper::SvXMLImportPropertyMapper(
61 : const rtl::Reference< XMLPropertySetMapper >& rMapper,
62 : SvXMLImport& rImp ):
63 : rImport(rImp),
64 27190 : maPropMapper ( rMapper )
65 : {
66 27190 : }
67 :
68 63212 : SvXMLImportPropertyMapper::~SvXMLImportPropertyMapper()
69 : {
70 27190 : mxNextMapper = 0;
71 36022 : }
72 :
73 7278 : void SvXMLImportPropertyMapper::ChainImportMapper(
74 : const rtl::Reference< SvXMLImportPropertyMapper>& rMapper )
75 : {
76 : // add map entries from rMapper to current map
77 7278 : maPropMapper->AddMapperEntry( rMapper->getPropertySetMapper() );
78 : // rMapper uses the same map as 'this'
79 7278 : rMapper->maPropMapper = maPropMapper;
80 :
81 : // set rMapper as last mapper in current chain
82 7278 : rtl::Reference< SvXMLImportPropertyMapper > xNext = mxNextMapper;
83 7278 : if( xNext.is())
84 : {
85 5838 : while( xNext->mxNextMapper.is())
86 730 : xNext = xNext->mxNextMapper;
87 2554 : xNext->mxNextMapper = rMapper;
88 : }
89 : else
90 4724 : mxNextMapper = rMapper;
91 :
92 : // if rMapper was already chained, correct
93 : // map pointer of successors
94 7278 : xNext = rMapper;
95 :
96 16624 : while( xNext->mxNextMapper.is())
97 : {
98 2068 : xNext = xNext->mxNextMapper;
99 2068 : xNext->maPropMapper = maPropMapper;
100 7278 : }
101 7278 : }
102 :
103 : /** fills the given itemset with the attributes in the given list */
104 31292 : void SvXMLImportPropertyMapper::importXML(
105 : vector< XMLPropertyState >& rProperties,
106 : Reference< XAttributeList > xAttrList,
107 : const SvXMLUnitConverter& rUnitConverter,
108 : const SvXMLNamespaceMap& rNamespaceMap,
109 : sal_uInt32 nPropType,
110 : sal_Int32 nStartIdx,
111 : sal_Int32 nEndIdx ) const
112 : {
113 31292 : sal_Int16 nAttr = xAttrList->getLength();
114 :
115 31292 : Reference< XNameContainer > xAttrContainer;
116 :
117 31292 : if( -1 == nStartIdx )
118 28604 : nStartIdx = 0;
119 31292 : if( -1 == nEndIdx )
120 28604 : nEndIdx = maPropMapper->GetEntryCount();
121 186850 : for( sal_Int16 i=0; i < nAttr; i++ )
122 : {
123 155558 : const OUString& rAttrName = xAttrList->getNameByIndex( i );
124 311116 : OUString aLocalName, aPrefix, aNamespace;
125 : sal_uInt16 nPrefix = rNamespaceMap.GetKeyByAttrName( rAttrName, &aPrefix,
126 155558 : &aLocalName, &aNamespace );
127 :
128 155558 : if( XML_NAMESPACE_XMLNS == nPrefix )
129 0 : continue;
130 :
131 311116 : const OUString& rValue = xAttrList->getValueByIndex( i );
132 :
133 : // index of actual property map entry
134 : // This looks very strange, but it works well:
135 : // If the start index is 0, the new value will become -1, and
136 : // GetEntryIndex will start searching with position 0.
137 : // Otherwise GetEntryIndex will start with the next position specified.
138 155558 : sal_Int32 nIndex = nStartIdx - 1;
139 155558 : sal_uInt32 nFlags = 0; // flags of actual property map entry
140 155558 : bool bFound = false;
141 :
142 : // for better error reporting: this should be set true if no
143 : // warning is needed
144 155558 : bool bNoWarning = false;
145 155558 : bool bAlienImport = false;
146 :
147 225558 : do
148 : {
149 : // find an entry for this attribute
150 : nIndex = maPropMapper->GetEntryIndex( nPrefix, aLocalName,
151 225558 : nPropType, nIndex );
152 :
153 225558 : if( nIndex > -1 && nIndex < nEndIdx )
154 : {
155 : // create a XMLPropertyState with an empty value
156 :
157 198942 : nFlags = maPropMapper->GetEntryFlags( nIndex );
158 198942 : if( (( nFlags & MID_FLAG_NO_PROPERTY ) == MID_FLAG_NO_PROPERTY) && (maPropMapper->GetEntryContextId( nIndex ) == CTF_ALIEN_ATTRIBUTE_IMPORT) )
159 : {
160 0 : bAlienImport = true;
161 0 : nIndex = -1;
162 : }
163 : else
164 : {
165 198942 : if( ( nFlags & MID_FLAG_ELEMENT_ITEM_IMPORT ) == 0 )
166 : {
167 198942 : XMLPropertyState aNewProperty( nIndex );
168 198942 : sal_Int32 nReference = -1;
169 :
170 : // if this is a multi attribute check if another attribute already set
171 : // this any. If so use this as a initial value
172 198942 : if( ( nFlags & MID_FLAG_MERGE_PROPERTY ) != 0 )
173 : {
174 18430 : const OUString aAPIName( maPropMapper->GetEntryAPIName( nIndex ) );
175 18430 : const sal_Int32 nSize = rProperties.size();
176 257868 : for( nReference = 0; nReference < nSize; nReference++ )
177 : {
178 246050 : sal_Int32 nRefIdx = rProperties[nReference].mnIndex;
179 484786 : if( (nRefIdx != -1) && (nIndex != nRefIdx) &&
180 238736 : (maPropMapper->GetEntryAPIName( nRefIdx ) == aAPIName ))
181 : {
182 6612 : aNewProperty = rProperties[nReference];
183 6612 : aNewProperty.mnIndex = nIndex;
184 6612 : break;
185 : }
186 : }
187 :
188 18430 : if( nReference == nSize )
189 11818 : nReference = -1;
190 : }
191 :
192 198942 : bool bSet = false;
193 198942 : if( ( nFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) == 0 )
194 : {
195 : // let the XMLPropertySetMapper decide how to import the value
196 181986 : bSet = maPropMapper->importXML( rValue, aNewProperty,
197 181986 : rUnitConverter );
198 : }
199 : else
200 : {
201 16956 : sal_uInt32 nOldSize = rProperties.size();
202 :
203 : bSet = handleSpecialItem( aNewProperty, rProperties,
204 : rValue, rUnitConverter,
205 16956 : rNamespaceMap );
206 :
207 : // no warning if handleSpecialItem added properties
208 16956 : bNoWarning |= ( nOldSize != rProperties.size() );
209 : }
210 :
211 : // no warning if we found could set the item. This
212 : // 'remembers' bSet across multi properties.
213 198942 : bNoWarning |= bSet;
214 :
215 : // store the property in the given vector
216 198942 : if( bSet )
217 : {
218 150168 : if( nReference == -1 )
219 143590 : rProperties.push_back( aNewProperty );
220 : else
221 6578 : rProperties[nReference] = aNewProperty;
222 : }
223 : else
224 : {
225 : // warn about unknown value. Unless it's a
226 : // multi property: Then we get another chance
227 : // to set the value.
228 50458 : if( !bNoWarning &&
229 1684 : ((nFlags & MID_FLAG_MULTI_PROPERTY) == 0) )
230 : {
231 146 : Sequence<OUString> aSeq(2);
232 146 : aSeq[0] = rAttrName;
233 146 : aSeq[1] = rValue;
234 : rImport.SetError( XMLERROR_FLAG_WARNING |
235 : XMLERROR_STYLE_ATTR_VALUE,
236 146 : aSeq );
237 : }
238 198942 : }
239 : }
240 198942 : bFound = true;
241 198942 : continue;
242 : }
243 : }
244 :
245 26616 : if( !bFound )
246 : {
247 : SAL_INFO_IF((XML_NAMESPACE_NONE != nPrefix) &&
248 : !(XML_NAMESPACE_UNKNOWN_FLAG & nPrefix) &&
249 : !bAlienImport, "xmloff.style",
250 : "unknown attribute: \"" << rAttrName << "\"");
251 2196 : if( (XML_NAMESPACE_UNKNOWN_FLAG & nPrefix) || (XML_NAMESPACE_NONE == nPrefix) || bAlienImport )
252 : {
253 0 : if( !xAttrContainer.is() )
254 : {
255 : // add an unknown attribute container to the properties
256 0 : Reference< XNameContainer > xNew( SvUnoAttributeContainer_CreateInstance(), UNO_QUERY );
257 0 : xAttrContainer = xNew;
258 :
259 : // find map entry and create new property state
260 0 : if( -1 == nIndex )
261 : {
262 0 : switch( nPropType )
263 : {
264 : case XML_TYPE_PROP_CHART:
265 0 : nIndex = maPropMapper->FindEntryIndex( "ChartUserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) );
266 0 : break;
267 : case XML_TYPE_PROP_PARAGRAPH:
268 0 : nIndex = maPropMapper->FindEntryIndex( "ParaUserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) );
269 0 : break;
270 : case XML_TYPE_PROP_TEXT:
271 0 : nIndex = maPropMapper->FindEntryIndex( "TextUserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) );
272 0 : break;
273 : default:
274 0 : break;
275 : }
276 : // other property type or property not found
277 0 : if( -1 == nIndex )
278 0 : nIndex = maPropMapper->FindEntryIndex( "UserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) );
279 : }
280 :
281 : // #106963#; use userdefined attribute only if it is in the specified property range
282 0 : if( nIndex != -1 && nIndex >= nStartIdx && nIndex < nEndIdx)
283 : {
284 0 : Any aAny;
285 0 : aAny <<= xAttrContainer;
286 0 : XMLPropertyState aNewProperty( nIndex, aAny );
287 :
288 : // push it on our stack so we export it later
289 0 : rProperties.push_back( aNewProperty );
290 0 : }
291 : }
292 :
293 0 : if( xAttrContainer.is() )
294 : {
295 0 : AttributeData aData;
296 0 : aData.Type = GetXMLToken( XML_CDATA );
297 0 : aData.Value = rValue;
298 :
299 0 : OUStringBuffer sName;
300 0 : if( XML_NAMESPACE_NONE != nPrefix )
301 : {
302 0 : sName.append( aPrefix );
303 0 : sName.append( ':' );
304 0 : aData.Namespace = aNamespace;
305 : }
306 :
307 0 : sName.append( aLocalName );
308 :
309 0 : Any aAny;
310 0 : aAny <<= aData;
311 0 : xAttrContainer->insertByName( sName.makeStringAndClear(), aAny );
312 : }
313 : }
314 : }
315 : }
316 198942 : while( ( nIndex >= 0 && nIndex + 1 < nEndIdx ) && (( nFlags & MID_FLAG_MULTI_PROPERTY ) != 0 ) );
317 155558 : }
318 :
319 31292 : finished( rProperties, nStartIdx, nEndIdx );
320 31292 : }
321 :
322 : /** this method is called for every item that has the MID_FLAG_SPECIAL_ITEM_IMPORT flag set */
323 7206 : bool SvXMLImportPropertyMapper::handleSpecialItem(
324 : XMLPropertyState& rProperty,
325 : vector< XMLPropertyState >& rProperties,
326 : const OUString& rValue,
327 : const SvXMLUnitConverter& rUnitConverter,
328 : const SvXMLNamespaceMap& rNamespaceMap ) const
329 : {
330 : OSL_ENSURE( mxNextMapper.is(), "unsupported special item in xml import" );
331 7206 : if( mxNextMapper.is() )
332 7206 : return mxNextMapper->handleSpecialItem( rProperty, rProperties, rValue,
333 7206 : rUnitConverter, rNamespaceMap );
334 : else
335 0 : return false;
336 : }
337 :
338 2698 : void SvXMLImportPropertyMapper::FillPropertySequence(
339 : const ::std::vector< XMLPropertyState >& rProperties,
340 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rValues )
341 : const
342 : {
343 2698 : sal_Int32 nCount = rProperties.size();
344 2698 : sal_Int32 nValueCount = 0;
345 2698 : rValues.realloc( nCount );
346 2698 : PropertyValue *pProps = rValues.getArray();
347 36958 : for( sal_Int32 i=0; i < nCount; i++ )
348 : {
349 34260 : const XMLPropertyState& rProp = rProperties[i];
350 34260 : sal_Int32 nIdx = rProp.mnIndex;
351 34260 : if( nIdx == -1 )
352 88 : continue;
353 34172 : pProps->Name = maPropMapper->GetEntryAPIName( nIdx );
354 34172 : if( !pProps->Name.isEmpty() )
355 : {
356 34172 : pProps->Value <<= rProp.maValue;
357 34172 : ++pProps;
358 34172 : ++nValueCount;
359 : }
360 : }
361 2698 : if( nValueCount < nCount )
362 42 : rValues.realloc( nValueCount );
363 2698 : }
364 :
365 11834 : void SvXMLImportPropertyMapper::CheckSpecialContext(
366 : const ::std::vector< XMLPropertyState >& aProperties,
367 : const ::com::sun::star::uno::Reference<
368 : ::com::sun::star::beans::XPropertySet > rPropSet,
369 : _ContextID_Index_Pair* pSpecialContextIds ) const
370 : {
371 : OSL_ENSURE( rPropSet.is(), "need an XPropertySet" );
372 11834 : sal_Int32 nCount = aProperties.size();
373 :
374 11834 : Reference< XPropertySetInfo > xInfo(rPropSet->getPropertySetInfo());
375 :
376 181124 : for( sal_Int32 i=0; i < nCount; i++ )
377 : {
378 169290 : const XMLPropertyState& rProp = aProperties[i];
379 169290 : sal_Int32 nIdx = rProp.mnIndex;
380 :
381 : // disregard property state if it has an invalid index
382 169290 : if( -1 == nIdx )
383 82 : continue;
384 :
385 169208 : const sal_Int32 nPropFlags = maPropMapper->GetEntryFlags( nIdx );
386 :
387 : // handle no-property and special items
388 338416 : if( ( pSpecialContextIds != NULL ) &&
389 338416 : ( ( 0 != ( nPropFlags & MID_FLAG_NO_PROPERTY_IMPORT ) ) ||
390 : ( 0 != ( nPropFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) ) ) )
391 : {
392 : // maybe it's one of our special context ids?
393 20382 : sal_Int16 nContextId = maPropMapper->GetEntryContextId(nIdx);
394 :
395 244096 : for ( sal_Int32 n = 0;
396 122048 : pSpecialContextIds[n].nContextID != -1;
397 : n++ )
398 : {
399 : // found: set index in pSpecialContextIds array
400 122020 : if ( pSpecialContextIds[n].nContextID == nContextId )
401 : {
402 20354 : pSpecialContextIds[n].nIndex = i;
403 20354 : break; // early out
404 : }
405 : }
406 : }
407 11834 : }
408 :
409 11834 : }
410 :
411 37632 : bool SvXMLImportPropertyMapper::FillPropertySet(
412 : const vector< XMLPropertyState >& aProperties,
413 : const Reference< XPropertySet > rPropSet,
414 : _ContextID_Index_Pair* pSpecialContextIds ) const
415 : {
416 37632 : bool bSet = false;
417 :
418 37632 : Reference< XTolerantMultiPropertySet > xTolPropSet( rPropSet, UNO_QUERY );
419 37632 : if (xTolPropSet.is())
420 : bSet = _FillTolerantMultiPropertySet( aProperties, xTolPropSet, maPropMapper, rImport,
421 2300 : pSpecialContextIds );
422 :
423 37632 : if (!bSet)
424 : {
425 : // get property set info
426 35432 : Reference< XPropertySetInfo > xInfo(rPropSet->getPropertySetInfo());
427 :
428 : // check for multi-property set
429 70864 : Reference<XMultiPropertySet> xMultiPropSet( rPropSet, UNO_QUERY );
430 35432 : if ( xMultiPropSet.is() )
431 : {
432 : // Try XMultiPropertySet. If that fails, try the regular route.
433 : bSet = _FillMultiPropertySet( aProperties, xMultiPropSet,
434 : xInfo, maPropMapper,
435 23104 : pSpecialContextIds );
436 23104 : if ( !bSet )
437 : bSet = _FillPropertySet( aProperties, rPropSet,
438 : xInfo, maPropMapper, rImport,
439 40 : pSpecialContextIds);
440 : }
441 : else
442 : bSet = _FillPropertySet( aProperties, rPropSet, xInfo,
443 : maPropMapper, rImport,
444 47760 : pSpecialContextIds );
445 : }
446 :
447 37632 : return bSet;
448 : }
449 :
450 12368 : bool SvXMLImportPropertyMapper::_FillPropertySet(
451 : const vector<XMLPropertyState> & rProperties,
452 : const Reference<XPropertySet> & rPropSet,
453 : const Reference<XPropertySetInfo> & rPropSetInfo,
454 : const rtl::Reference<XMLPropertySetMapper> & rPropMapper,
455 : SvXMLImport& rImport,
456 : _ContextID_Index_Pair* pSpecialContextIds )
457 : {
458 : OSL_ENSURE( rPropSet.is(), "need an XPropertySet" );
459 : OSL_ENSURE( rPropSetInfo.is(), "need an XPropertySetInfo" );
460 :
461 : // preliminaries
462 12368 : bool bSet = false;
463 12368 : sal_Int32 nCount = rProperties.size();
464 :
465 : // iterate over property states that we want to set
466 79444 : for( sal_Int32 i=0; i < nCount; i++ )
467 : {
468 67076 : const XMLPropertyState& rProp = rProperties[i];
469 67076 : sal_Int32 nIdx = rProp.mnIndex;
470 :
471 : // disregard property state if it has an invalid index
472 67076 : if( -1 == nIdx )
473 14760 : continue;
474 :
475 52316 : const OUString& rPropName = rPropMapper->GetEntryAPIName( nIdx );
476 52316 : const sal_Int32 nPropFlags = rPropMapper->GetEntryFlags( nIdx );
477 :
478 152816 : if ( ( 0 == ( nPropFlags & MID_FLAG_NO_PROPERTY ) ) &&
479 102280 : ( ( 0 != ( nPropFlags & MID_FLAG_MUST_EXIST ) ) ||
480 51140 : rPropSetInfo->hasPropertyByName( rPropName ) ) )
481 : {
482 : // try setting the property
483 : try
484 : {
485 49360 : rPropSet->setPropertyValue( rPropName, rProp.maValue );
486 49284 : bSet = true;
487 : }
488 80 : catch ( const IllegalArgumentException& e )
489 : {
490 : // illegal value: check whether this property is
491 : // allowed to throw this exception
492 40 : if ( 0 == ( nPropFlags & MID_FLAG_PROPERTY_MAY_THROW ) )
493 : {
494 40 : Sequence<OUString> aSeq(1);
495 40 : aSeq[0] = rPropName;
496 : rImport.SetError(
497 : XMLERROR_STYLE_PROP_VALUE | XMLERROR_FLAG_ERROR,
498 40 : aSeq, e.Message, NULL );
499 : }
500 : }
501 72 : catch ( const UnknownPropertyException& e )
502 : {
503 : // unknown property: This is always an error!
504 36 : Sequence<OUString> aSeq(1);
505 36 : aSeq[0] = rPropName;
506 : rImport.SetError(
507 : XMLERROR_STYLE_PROP_UNKNOWN | XMLERROR_FLAG_ERROR,
508 36 : aSeq, e.Message, NULL );
509 : }
510 0 : catch ( const PropertyVetoException& e )
511 : {
512 : // property veto: this shouldn't happen
513 0 : Sequence<OUString> aSeq(1);
514 0 : aSeq[0] = rPropName;
515 : rImport.SetError(
516 : XMLERROR_STYLE_PROP_OTHER | XMLERROR_FLAG_ERROR,
517 0 : aSeq, e.Message, NULL );
518 : }
519 0 : catch ( const WrappedTargetException& e )
520 : {
521 : // wrapped target: this shouldn't happen either
522 0 : Sequence<OUString> aSeq(1);
523 0 : aSeq[0] = rPropName;
524 : rImport.SetError(
525 : XMLERROR_STYLE_PROP_OTHER | XMLERROR_FLAG_ERROR,
526 0 : aSeq, e.Message, NULL );
527 : }
528 : }
529 :
530 : // handle no-property and special items
531 88384 : if( ( pSpecialContextIds != NULL ) &&
532 70960 : ( ( 0 != ( nPropFlags & MID_FLAG_NO_PROPERTY_IMPORT ) ) ||
533 : ( 0 != ( nPropFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) ) ) )
534 : {
535 : // maybe it's one of our special context ids?
536 3656 : sal_Int16 nContextId = rPropMapper->GetEntryContextId(nIdx);
537 :
538 60708 : for ( sal_Int32 n = 0;
539 30354 : pSpecialContextIds[n].nContextID != -1;
540 : n++ )
541 : {
542 : // found: set index in pSpecialContextIds array
543 28452 : if ( pSpecialContextIds[n].nContextID == nContextId )
544 : {
545 1754 : pSpecialContextIds[n].nIndex = i;
546 1754 : break; // early out
547 : }
548 : }
549 : }
550 : }
551 :
552 12368 : return bSet;
553 : }
554 :
555 :
556 :
557 : typedef pair<const OUString*, const Any* > PropertyPair;
558 : typedef vector<PropertyPair> PropertyPairs;
559 :
560 : struct PropertyPairLessFunctor :
561 : public std::binary_function<PropertyPair, PropertyPair, bool>
562 : {
563 1102296 : bool operator()( const PropertyPair& a, const PropertyPair& b ) const
564 : {
565 1102296 : return (*a.first < *b.first);
566 : }
567 : };
568 :
569 25404 : void SvXMLImportPropertyMapper::_PrepareForMultiPropertySet(
570 : const vector<XMLPropertyState> & rProperties,
571 : const Reference<XPropertySetInfo> & rPropSetInfo,
572 : const rtl::Reference<XMLPropertySetMapper> & rPropMapper,
573 : _ContextID_Index_Pair* pSpecialContextIds,
574 : Sequence<OUString>& rNames,
575 : Sequence<Any>& rValues)
576 : {
577 25404 : sal_Int32 nCount = rProperties.size();
578 :
579 : // property pairs structure stores names + values of properties to be set.
580 25404 : PropertyPairs aPropertyPairs;
581 25404 : aPropertyPairs.reserve( nCount );
582 :
583 : // iterate over property states that we want to set
584 : sal_Int32 i;
585 281330 : for( i = 0; i < nCount; i++ )
586 : {
587 255926 : const XMLPropertyState& rProp = rProperties[i];
588 255926 : sal_Int32 nIdx = rProp.mnIndex;
589 :
590 : // disregard property state if it has an invalid index
591 255926 : if( -1 == nIdx )
592 9254 : continue;
593 :
594 246672 : const OUString& rPropName = rPropMapper->GetEntryAPIName( nIdx );
595 246672 : const sal_Int32 nPropFlags = rPropMapper->GetEntryFlags( nIdx );
596 :
597 733166 : if ( ( 0 == ( nPropFlags & MID_FLAG_NO_PROPERTY ) ) &&
598 492208 : ( ( 0 != ( nPropFlags & MID_FLAG_MUST_EXIST ) ) ||
599 463556 : !rPropSetInfo.is() ||
600 434904 : (rPropSetInfo.is() && rPropSetInfo->hasPropertyByName( rPropName )) ) )
601 : {
602 : // save property into property pair structure
603 240390 : aPropertyPairs.push_back( PropertyPair( &rPropName, &rProp.maValue ) );
604 : }
605 :
606 : // handle no-property and special items
607 440262 : if( ( pSpecialContextIds != NULL ) &&
608 386612 : ( ( 0 != ( nPropFlags & MID_FLAG_NO_PROPERTY_IMPORT ) ) ||
609 : ( 0 != ( nPropFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) ) ) )
610 : {
611 : // maybe it's one of our special context ids?
612 21482 : sal_Int16 nContextId = rPropMapper->GetEntryContextId(nIdx);
613 353888 : for ( sal_Int32 n = 0;
614 176944 : pSpecialContextIds[n].nContextID != -1;
615 : n++ )
616 : {
617 : // found: set index in pSpecialContextIds array
618 169762 : if ( pSpecialContextIds[n].nContextID == nContextId )
619 : {
620 14300 : pSpecialContextIds[n].nIndex = i;
621 14300 : break; // early out
622 : }
623 : }
624 : }
625 : }
626 :
627 : // We now need to construct the sequences and actually the set
628 : // values.
629 :
630 : // sort the property pairs
631 : sort( aPropertyPairs.begin(), aPropertyPairs.end(),
632 25404 : PropertyPairLessFunctor());
633 :
634 : // create sequences
635 25404 : rNames.realloc( aPropertyPairs.size() );
636 25404 : OUString* pNamesArray = rNames.getArray();
637 25404 : rValues.realloc( aPropertyPairs.size() );
638 25404 : Any* pValuesArray = rValues.getArray();
639 :
640 : // copy values into sequences
641 25404 : i = 0;
642 797382 : for( PropertyPairs::iterator aIter = aPropertyPairs.begin();
643 531588 : aIter != aPropertyPairs.end();
644 : ++aIter )
645 : {
646 240390 : pNamesArray[i] = *(aIter->first);
647 240390 : pValuesArray[i++] = *(aIter->second);
648 25404 : }
649 25404 : }
650 :
651 23104 : bool SvXMLImportPropertyMapper::_FillMultiPropertySet(
652 : const vector<XMLPropertyState> & rProperties,
653 : const Reference<XMultiPropertySet> & rMultiPropSet,
654 : const Reference<XPropertySetInfo> & rPropSetInfo,
655 : const rtl::Reference<XMLPropertySetMapper> & rPropMapper,
656 : _ContextID_Index_Pair* pSpecialContextIds )
657 : {
658 : OSL_ENSURE( rMultiPropSet.is(), "Need multi property set. ");
659 : OSL_ENSURE( rPropSetInfo.is(), "Need property set info." );
660 :
661 23104 : bool bSuccessful = false;
662 :
663 23104 : Sequence<OUString> aNames;
664 46208 : Sequence<Any> aValues;
665 :
666 : _PrepareForMultiPropertySet(rProperties, rPropSetInfo, rPropMapper, pSpecialContextIds,
667 23104 : aNames, aValues);
668 :
669 : // and, finally, try to set the values
670 : try
671 : {
672 23104 : rMultiPropSet->setPropertyValues( aNames, aValues );
673 23064 : bSuccessful = true;
674 : }
675 40 : catch ( ... )
676 : {
677 : OSL_ENSURE(bSuccessful, "Exception caught; style may not be imported correctly.");
678 : }
679 :
680 46208 : return bSuccessful;
681 : }
682 :
683 2300 : bool SvXMLImportPropertyMapper::_FillTolerantMultiPropertySet(
684 : const vector<XMLPropertyState> & rProperties,
685 : const Reference<XTolerantMultiPropertySet> & rTolMultiPropSet,
686 : const rtl::Reference<XMLPropertySetMapper> & rPropMapper,
687 : SvXMLImport& rImport,
688 : _ContextID_Index_Pair* pSpecialContextIds )
689 : {
690 : OSL_ENSURE( rTolMultiPropSet.is(), "Need tolerant multi property set. ");
691 :
692 2300 : bool bSuccessful = false;
693 :
694 2300 : Sequence<OUString> aNames;
695 4600 : Sequence<Any> aValues;
696 :
697 : _PrepareForMultiPropertySet(rProperties, Reference<XPropertySetInfo>(NULL), rPropMapper, pSpecialContextIds,
698 2300 : aNames, aValues);
699 :
700 : // and, finally, try to set the values
701 : try
702 : {
703 2300 : Sequence< SetPropertyTolerantFailed > aResults(rTolMultiPropSet->setPropertyValuesTolerant( aNames, aValues ));
704 2300 : if (aResults.getLength() == 0)
705 2200 : bSuccessful = true;
706 : else
707 : {
708 100 : sal_Int32 nCount(aResults.getLength());
709 260 : for( sal_Int32 i = 0; i < nCount; ++i)
710 : {
711 160 : Sequence<OUString> aSeq(1);
712 160 : aSeq[0] = aResults[i].Name;
713 320 : OUString sMessage;
714 160 : switch (aResults[i].Result)
715 : {
716 : case TolerantPropertySetResultType::UNKNOWN_PROPERTY :
717 120 : sMessage = "UNKNOWN_PROPERTY";
718 120 : break;
719 : case TolerantPropertySetResultType::ILLEGAL_ARGUMENT :
720 40 : sMessage = "ILLEGAL_ARGUMENT";
721 40 : break;
722 : case TolerantPropertySetResultType::PROPERTY_VETO :
723 0 : sMessage = "PROPERTY_VETO";
724 0 : break;
725 : case TolerantPropertySetResultType::WRAPPED_TARGET :
726 0 : sMessage = "WRAPPED_TARGET";
727 0 : break;
728 : };
729 : rImport.SetError(
730 : XMLERROR_STYLE_PROP_OTHER | XMLERROR_FLAG_ERROR,
731 160 : aSeq, sMessage, NULL );
732 160 : }
733 2300 : }
734 : }
735 0 : catch ( ... )
736 : {
737 : OSL_ENSURE(bSuccessful, "Exception caught; style may not be imported correctly.");
738 : }
739 :
740 4600 : return bSuccessful;
741 : }
742 :
743 16220 : void SvXMLImportPropertyMapper::finished(
744 : vector< XMLPropertyState >& rProperties,
745 : sal_Int32 nStartIndex, sal_Int32 nEndIndex ) const
746 : {
747 : // nothing to do here
748 16220 : if( mxNextMapper.is() )
749 9618 : mxNextMapper->finished( rProperties, nStartIndex, nEndIndex );
750 16220 : }
751 :
752 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|