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