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