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