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