xref: /trunk/main/xmloff/source/forms/propertyimport.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 #include "propertyimport.hxx"
31 #include <xmloff/xmlimp.hxx>
32 #include <xmloff/xmluconv.hxx>
33 #include <xmloff/nmspmap.hxx>
34 #include <osl/diagnose.h>
35 #include <comphelper/extract.hxx>
36 #include "callbacks.hxx"
37 #include "xmloff/xmlnmspe.hxx"
38 #include <tools/date.hxx>
39 #include <tools/time.hxx>
40 #include <tools/datetime.hxx>
41 #include <com/sun/star/util/Date.hpp>
42 #include <com/sun/star/util/Time.hpp>
43 #include <com/sun/star/util/DateTime.hpp>
44 #include <unotools/datetime.hxx>
45 #include <rtl/logfile.hxx>
46 
47 #if OSL_DEBUG_LEVEL > 0
48     #ifndef _OSL_THREAD_H_
49     #include <osl/thread.h>
50     #endif
51 #endif
52 
53 //.........................................................................
54 namespace xmloff
55 {
56 //.........................................................................
57 
58     using namespace ::com::sun::star::uno;
59     using namespace ::com::sun::star::beans;
60     using namespace ::com::sun::star::xml;
61 
62     // NO using namespace ...util !!!
63     // need a tools Date/Time/DateTime below, which would conflict with the uno types then
64 
65 #define TYPE_DATE       1
66 #define TYPE_TIME       2
67 #define TYPE_DATETIME   3
68 
69 //=====================================================================
70 //= PropertyConversion
71 //=====================================================================
72 namespace
73 {
74     //---------------------------------------------------------------------
75     ::com::sun::star::util::Time lcl_getTime(double _nValue)
76     {
77         ::com::sun::star::util::Time aTime;
78         sal_uInt32 nIntValue = sal_Int32(_nValue * 8640000);
79         nIntValue *= 8640000;
80         aTime.HundredthSeconds = (sal_uInt16)( nIntValue % 100 );
81         nIntValue /= 100;
82         aTime.Seconds = (sal_uInt16)( nIntValue % 60 );
83         nIntValue /= 60;
84         aTime.Minutes = (sal_uInt16)( nIntValue % 60 );
85         nIntValue /= 60;
86         OSL_ENSURE(nIntValue < 24, "lcl_getTime: more than a day?");
87         aTime.Hours = static_cast< sal_uInt16 >( nIntValue );
88 
89         return aTime;
90     }
91 
92     //---------------------------------------------------------------------
93     static ::com::sun::star::util::Date lcl_getDate( double _nValue )
94     {
95         Date aToolsDate((sal_uInt32)_nValue);
96         ::com::sun::star::util::Date aDate;
97         ::utl::typeConvert(aToolsDate, aDate);
98         return aDate;
99     }
100 }
101 
102 //---------------------------------------------------------------------
103 Any PropertyConversion::convertString( SvXMLImport& _rImporter, const ::com::sun::star::uno::Type& _rExpectedType,
104     const ::rtl::OUString& _rReadCharacters, const SvXMLEnumMapEntry* _pEnumMap, const sal_Bool _bInvertBoolean )
105 {
106     Any aReturn;
107     sal_Bool bEnumAsInt = sal_False;
108     switch (_rExpectedType.getTypeClass())
109     {
110         case TypeClass_BOOLEAN:     // sal_Bool
111         {
112             sal_Bool bValue;
113         #if OSL_DEBUG_LEVEL > 0
114             sal_Bool bSuccess =
115         #endif
116             _rImporter.GetMM100UnitConverter().convertBool(bValue, _rReadCharacters);
117             OSL_ENSURE(bSuccess,
118                     ::rtl::OString("PropertyConversion::convertString: could not convert \"")
119                 +=  ::rtl::OString(_rReadCharacters.getStr(), _rReadCharacters.getLength(), RTL_TEXTENCODING_ASCII_US)
120                 +=  ::rtl::OString("\" into a boolean!"));
121             aReturn = ::cppu::bool2any(_bInvertBoolean ? !bValue : bValue);
122         }
123         break;
124         case TypeClass_SHORT:       // sal_Int16
125         case TypeClass_LONG:        // sal_Int32
126             if (!_pEnumMap)
127             {   // it's a real int32/16 property
128                 sal_Int32 nValue(0);
129         #if OSL_DEBUG_LEVEL > 0
130                 sal_Bool bSuccess =
131         #endif
132                 _rImporter.GetMM100UnitConverter().convertNumber(nValue, _rReadCharacters);
133                 OSL_ENSURE(bSuccess,
134                         ::rtl::OString("PropertyConversion::convertString: could not convert \"")
135                     +=  ::rtl::OString(_rReadCharacters.getStr(), _rReadCharacters.getLength(), RTL_TEXTENCODING_ASCII_US)
136                     +=  ::rtl::OString("\" into an integer!"));
137                 if (TypeClass_SHORT == _rExpectedType.getTypeClass())
138                     aReturn <<= (sal_Int16)nValue;
139                 else
140                     aReturn <<= (sal_Int32)nValue;
141                 break;
142             }
143             bEnumAsInt = sal_True;
144             // NO BREAK! handle it as enum
145         case TypeClass_ENUM:
146         {
147             sal_uInt16 nEnumValue(0);
148         #if OSL_DEBUG_LEVEL > 0
149             sal_Bool bSuccess =
150         #endif
151             _rImporter.GetMM100UnitConverter().convertEnum(nEnumValue, _rReadCharacters, _pEnumMap);
152             OSL_ENSURE(bSuccess, "PropertyConversion::convertString: could not convert to an enum value!");
153             if (bEnumAsInt)
154                 if (TypeClass_SHORT == _rExpectedType.getTypeClass())
155                     aReturn <<= (sal_Int16)nEnumValue;
156                 else
157                     aReturn <<= (sal_Int32)nEnumValue;
158             else
159                 aReturn = ::cppu::int2enum((sal_Int32)nEnumValue, _rExpectedType);
160         }
161         break;
162         case TypeClass_HYPER:
163         {
164             OSL_ENSURE(sal_False, "PropertyConversion::convertString: 64-bit integers not implemented yet!");
165         }
166         break;
167         case TypeClass_DOUBLE:
168         {
169             double nValue;
170         #if OSL_DEBUG_LEVEL > 0
171             sal_Bool bSuccess =
172         #endif
173             _rImporter.GetMM100UnitConverter().convertDouble(nValue, _rReadCharacters);
174             OSL_ENSURE(bSuccess,
175                     ::rtl::OString("PropertyConversion::convertString: could not convert \"")
176                 +=  ::rtl::OString(_rReadCharacters.getStr(), _rReadCharacters.getLength(), RTL_TEXTENCODING_ASCII_US)
177                 +=  ::rtl::OString("\" into a double!"));
178             aReturn <<= (double)nValue;
179         }
180         break;
181         case TypeClass_STRING:
182             aReturn <<= _rReadCharacters;
183             break;
184         case TypeClass_STRUCT:
185         {
186             sal_Int32 nType = 0;
187             if ( _rExpectedType.equals( ::cppu::UnoType< ::com::sun::star::util::Date >::get() ) )
188                 nType = TYPE_DATE;
189             else if ( _rExpectedType.equals( ::cppu::UnoType< ::com::sun::star::util::Time >::get() ) )
190                 nType = TYPE_TIME;
191             else  if ( _rExpectedType.equals( ::cppu::UnoType< ::com::sun::star::util::DateTime >::get() ) )
192                 nType = TYPE_DATETIME;
193 
194             if ( nType )
195             {
196                 // first extract the double
197                 double nValue = 0;
198             #if OSL_DEBUG_LEVEL > 0
199                 sal_Bool bSuccess =
200             #endif
201                 _rImporter.GetMM100UnitConverter().convertDouble(nValue, _rReadCharacters);
202                 OSL_ENSURE(bSuccess,
203                         ::rtl::OString("PropertyConversion::convertString: could not convert \"")
204                     +=  ::rtl::OString(_rReadCharacters.getStr(), _rReadCharacters.getLength(), RTL_TEXTENCODING_ASCII_US)
205                     +=  ::rtl::OString("\" into a double!"));
206 
207                 // then convert it into the target type
208                 switch (nType)
209                 {
210                     case TYPE_DATE:
211                     {
212                         OSL_ENSURE(((sal_uInt32)nValue) - nValue == 0,
213                             "PropertyConversion::convertString: a Date value with a fractional part?");
214                         aReturn <<= lcl_getDate(nValue);
215                     }
216                     break;
217                     case TYPE_TIME:
218                     {
219                         OSL_ENSURE(((sal_uInt32)nValue) == 0,
220                             "PropertyConversion::convertString: a Time value with more than a fractional part?");
221                         aReturn <<= lcl_getTime(nValue);
222                     }
223                     break;
224                     case TYPE_DATETIME:
225                     {
226                         ::com::sun::star::util::Time aTime = lcl_getTime(nValue);
227                         ::com::sun::star::util::Date aDate = lcl_getDate(nValue);
228 
229                         ::com::sun::star::util::DateTime aDateTime;
230                         aDateTime.HundredthSeconds = aTime.HundredthSeconds;
231                         aDateTime.Seconds = aTime.Seconds;
232                         aDateTime.Minutes = aTime.Minutes;
233                         aDateTime.Hours = aTime.Hours;
234                         aDateTime.Day = aDate.Day;
235                         aDateTime.Month = aDate.Month;
236                         aDateTime.Year = aDate.Year;
237                         aReturn <<= aDateTime;
238                     }
239                     break;
240                 }
241             }
242             else
243                 OSL_ENSURE(sal_False, "PropertyConversion::convertString: unsupported property type!");
244         }
245         break;
246         default:
247             OSL_ENSURE(sal_False, "PropertyConversion::convertString: invalid type class!");
248     }
249 
250     return aReturn;
251 }
252 
253 //---------------------------------------------------------------------
254 Type PropertyConversion::xmlTypeToUnoType( const ::rtl::OUString& _rType )
255 {
256     Type aUnoType( ::getVoidCppuType() );
257 
258     DECLARE_STL_USTRINGACCESS_MAP( ::com::sun::star::uno::Type, MapString2Type );
259     static MapString2Type s_aTypeNameMap;
260     if ( s_aTypeNameMap.empty() )
261     {
262         s_aTypeNameMap[ token::GetXMLToken( token::XML_BOOLEAN ) ] = ::getBooleanCppuType();
263         s_aTypeNameMap[ token::GetXMLToken( token::XML_FLOAT )   ] = ::getCppuType( static_cast< double* >(NULL) );
264         s_aTypeNameMap[ token::GetXMLToken( token::XML_STRING )  ] = ::getCppuType( static_cast< ::rtl::OUString* >(NULL) );
265         s_aTypeNameMap[ token::GetXMLToken( token::XML_VOID )    ] = ::getVoidCppuType();
266     }
267 
268     const ConstMapString2TypeIterator aTypePos = s_aTypeNameMap.find( _rType );
269     OSL_ENSURE( s_aTypeNameMap.end() != aTypePos, "PropertyConversion::xmlTypeToUnoType: invalid property name!" );
270     if ( s_aTypeNameMap.end() != aTypePos )
271         aUnoType = aTypePos->second;
272 
273     return aUnoType;
274 }
275 
276 //=====================================================================
277 //= OPropertyImport
278 //=====================================================================
279 //---------------------------------------------------------------------
280 OPropertyImport::OPropertyImport(OFormLayerXMLImport_Impl& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName)
281     :SvXMLImportContext(_rImport.getGlobalContext(), _nPrefix, _rName)
282     ,m_rContext(_rImport)
283     ,m_bTrackAttributes(sal_False)
284 {
285 }
286 
287 //---------------------------------------------------------------------
288 SvXMLImportContext* OPropertyImport::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
289     const Reference< sax::XAttributeList >& _rxAttrList)
290 {
291     if( token::IsXMLToken( _rLocalName, token::XML_PROPERTIES) )
292     {
293         return new OPropertyElementsContext( m_rContext.getGlobalContext(),
294                                              _nPrefix, _rLocalName, this);
295     }
296     else
297     {
298         OSL_ENSURE(sal_False,
299                 ::rtl::OString("OPropertyImport::CreateChildContext: unknown sub element (only \"properties\" is recognized, but it is ")
300             +=  ::rtl::OString(_rLocalName.getStr(), _rLocalName.getLength(), RTL_TEXTENCODING_ASCII_US)
301             +=  ::rtl::OString(")!"));
302         return SvXMLImportContext::CreateChildContext(_nPrefix, _rLocalName, _rxAttrList);
303     }
304 }
305 
306 //---------------------------------------------------------------------
307 void OPropertyImport::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
308 {
309     OSL_ENSURE(_rxAttrList.is(), "OPropertyImport::StartElement: invalid attribute list!");
310     const sal_Int32 nAttributeCount = _rxAttrList->getLength();
311 
312     // assume the 'worst' case: all attributes describe properties. This should save our property array
313     // some reallocs
314     m_aValues.reserve(nAttributeCount);
315 
316     const SvXMLNamespaceMap& rMap = m_rContext.getGlobalContext().GetNamespaceMap();
317     sal_uInt16 nNamespace;
318     ::rtl::OUString sLocalName;
319     for (sal_Int16 i=0; i<nAttributeCount; ++i)
320     {
321         nNamespace = rMap.GetKeyByAttrName(_rxAttrList->getNameByIndex(i), &sLocalName);
322         handleAttribute(nNamespace, sLocalName, _rxAttrList->getValueByIndex(i));
323 
324         if (m_bTrackAttributes)
325             m_aEncounteredAttributes.insert(sLocalName);
326     }
327 
328     // TODO: create PropertyValues for all the attributes which were not present, because they were implied
329     // this is necessary as soon as we have properties where the XML default is different from the property
330     // default
331 }
332 
333 //---------------------------------------------------------------------
334 sal_Bool OPropertyImport::encounteredAttribute(const ::rtl::OUString& _rAttributeName) const
335 {
336     OSL_ENSURE(m_bTrackAttributes, "OPropertyImport::encounteredAttribute: attribute tracking not enabled!");
337     return m_aEncounteredAttributes.end() != m_aEncounteredAttributes.find(_rAttributeName);
338 }
339 
340 //---------------------------------------------------------------------
341 void OPropertyImport::Characters(const ::rtl::OUString&
342 #if OSL_DEBUG_LEVEL > 0
343 _rChars
344 #endif
345 )
346 {
347     // ignore them (should be whitespaces only)
348     OSL_ENSURE(0 == _rChars.trim().getLength(), "OPropertyImport::Characters: non-whitespace characters!");
349 }
350 
351 //---------------------------------------------------------------------
352 bool OPropertyImport::handleAttribute(sal_uInt16 /*_nNamespaceKey*/, const ::rtl::OUString& _rLocalName, const ::rtl::OUString& _rValue)
353 {
354     const OAttribute2Property::AttributeAssignment* pProperty = m_rContext.getAttributeMap().getAttributeTranslation(_rLocalName);
355     if (pProperty)
356     {
357         // create and store a new PropertyValue
358         PropertyValue aNewValue;
359         aNewValue.Name = pProperty->sPropertyName;
360 
361         // convert the value string into the target type
362         aNewValue.Value = PropertyConversion::convertString(m_rContext.getGlobalContext(), pProperty->aPropertyType, _rValue, pProperty->pEnumMap, pProperty->bInverseSemantics);
363         implPushBackPropertyValue( aNewValue );
364         return true;
365     }
366     if (!token::IsXMLToken(_rLocalName, token::XML_TYPE))  // xlink:type is valid but ignored for <form:form>
367     {
368 #if OSL_DEBUG_LEVEL > 0
369         ::rtl::OString sMessage( "OPropertyImport::handleAttribute: Can't handle the following:\n" );
370         sMessage += ::rtl::OString( "  Attribute name: " );
371         sMessage += ::rtl::OString( _rLocalName.getStr(), _rLocalName.getLength(), osl_getThreadTextEncoding() );
372         sMessage += ::rtl::OString( "\n  value: " );
373         sMessage += ::rtl::OString( _rValue.getStr(), _rValue.getLength(), osl_getThreadTextEncoding() );
374         OSL_ENSURE( sal_False, sMessage.getStr() );
375 #endif
376         return false;
377     }
378     return true;
379 }
380 
381 //=====================================================================
382 //= OPropertyElementsContext
383 //=====================================================================
384 //---------------------------------------------------------------------
385 OPropertyElementsContext::OPropertyElementsContext(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
386         const OPropertyImportRef& _rPropertyImporter)
387     :SvXMLImportContext(_rImport, _nPrefix, _rName)
388     ,m_xPropertyImporter(_rPropertyImporter)
389 {
390 }
391 
392 //---------------------------------------------------------------------
393 SvXMLImportContext* OPropertyElementsContext::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
394     const Reference< sax::XAttributeList >&)
395 {
396     if( token::IsXMLToken( _rLocalName, token::XML_PROPERTY ) )
397     {
398         return new OSinglePropertyContext(GetImport(), _nPrefix, _rLocalName, m_xPropertyImporter);
399     }
400     else if( token::IsXMLToken( _rLocalName, token::XML_LIST_PROPERTY ) )
401     {
402         return new OListPropertyContext( GetImport(), _nPrefix, _rLocalName, m_xPropertyImporter );
403     }
404     else
405     {
406         OSL_ENSURE(sal_False,
407                 ::rtl::OString("OPropertyElementsContext::CreateChildContext: unknown child element (\"")
408             +=  ::rtl::OString(_rLocalName.getStr(), _rLocalName.getLength(), RTL_TEXTENCODING_ASCII_US)
409             +=  ::rtl::OString("\")!"));
410         return new SvXMLImportContext(GetImport(), _nPrefix, _rLocalName);
411     }
412 }
413 
414 #if OSL_DEBUG_LEVEL > 0
415     //---------------------------------------------------------------------
416     void OPropertyElementsContext::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
417     {
418         OSL_ENSURE(0 == _rxAttrList->getLength(), "OPropertyElementsContext::StartElement: the form:properties element should not have attributes!");
419         SvXMLImportContext::StartElement(_rxAttrList);
420     }
421 
422     //---------------------------------------------------------------------
423     void OPropertyElementsContext::Characters(const ::rtl::OUString& _rChars)
424     {
425         OSL_ENSURE(0 == _rChars.trim(), "OPropertyElementsContext::Characters: non-whitespace characters detected!");
426         SvXMLImportContext::Characters(_rChars);
427     }
428 
429 #endif
430 
431 //=====================================================================
432 //= OSinglePropertyContext
433 //=====================================================================
434 //---------------------------------------------------------------------
435 OSinglePropertyContext::OSinglePropertyContext(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
436         const OPropertyImportRef& _rPropertyImporter)
437     :SvXMLImportContext(_rImport, _nPrefix, _rName)
438     ,m_xPropertyImporter(_rPropertyImporter)
439 {
440 }
441 
442 //---------------------------------------------------------------------
443 SvXMLImportContext* OSinglePropertyContext::CreateChildContext(sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName,
444         const Reference< sax::XAttributeList >&)
445 {
446     OSL_ENSURE(sal_False,
447             ::rtl::OString("OSinglePropertyContext::CreateChildContext: unknown child element (\"")
448         +=  ::rtl::OString(_rLocalName.getStr(), _rLocalName.getLength(), RTL_TEXTENCODING_ASCII_US)
449         +=  ::rtl::OString("\")!"));
450     return new SvXMLImportContext(GetImport(), _nPrefix, _rLocalName);
451 }
452 
453 //---------------------------------------------------------------------
454 void OSinglePropertyContext::StartElement(const Reference< sax::XAttributeList >& _rxAttrList)
455 {
456     ::com::sun::star::beans::PropertyValue aPropValue;      // the property the instance imports currently
457     ::com::sun::star::uno::Type aPropType;          // the type of the property the instance imports currently
458 
459     ::rtl::OUString sType, sValue;
460     const SvXMLNamespaceMap& rMap = GetImport().GetNamespaceMap();
461     const sal_Int16 nAttrCount = _rxAttrList.is() ? _rxAttrList->getLength() : 0;
462     for( sal_Int16 i=0; i < nAttrCount; i++ )
463     {
464         const ::rtl::OUString& rAttrName = _rxAttrList->getNameByIndex( i );
465         //const ::rtl::OUString& rValue = _rxAttrList->getValueByIndex( i );
466 
467         ::rtl::OUString aLocalName;
468         sal_uInt16 nPrefix =
469             rMap.GetKeyByAttrName( rAttrName,
470                                                             &aLocalName );
471         if( XML_NAMESPACE_FORM == nPrefix )
472         {
473             if( token::IsXMLToken( aLocalName, token::XML_PROPERTY_NAME ) )
474                 aPropValue.Name = _rxAttrList->getValueByIndex( i );
475 
476         }
477         else if( XML_NAMESPACE_OFFICE == nPrefix )
478         {
479             if( token::IsXMLToken( aLocalName, token::XML_VALUE_TYPE ) )
480                 sType = _rxAttrList->getValueByIndex( i );
481             else if( token::IsXMLToken( aLocalName,
482                                         token::XML_VALUE ) ||
483                      token::IsXMLToken( aLocalName,
484                                         token::XML_BOOLEAN_VALUE ) ||
485                      token::IsXMLToken( aLocalName,
486                                         token::XML_STRING_VALUE ) )
487                 sValue = _rxAttrList->getValueByIndex( i );
488         }
489     }
490 
491     // the name of the property
492     OSL_ENSURE(aPropValue.Name.getLength(), "OSinglePropertyContext::StartElement: invalid property name!");
493 
494     // needs to be translated into a ::com::sun::star::uno::Type
495     aPropType = PropertyConversion::xmlTypeToUnoType( sType );
496     if( TypeClass_VOID == aPropType.getTypeClass() )
497     {
498         aPropValue.Value = Any();
499     }
500     else
501     {
502         aPropValue.Value =
503             PropertyConversion::convertString(GetImport(), aPropType,
504                                            sValue);
505     }
506 
507     // now that we finally have our property value, add it to our parent object
508     if( aPropValue.Name.getLength() )
509         m_xPropertyImporter->implPushBackGenericPropertyValue(aPropValue);
510 }
511 
512 //=====================================================================
513 //= OListPropertyContext
514 //=====================================================================
515 //---------------------------------------------------------------------
516 OListPropertyContext::OListPropertyContext( SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName,
517     const OPropertyImportRef& _rPropertyImporter )
518     :SvXMLImportContext( _rImport, _nPrefix, _rName )
519     ,m_xPropertyImporter( _rPropertyImporter )
520 {
521 }
522 
523 //---------------------------------------------------------------------
524 void OListPropertyContext::StartElement( const Reference< sax::XAttributeList >& _rxAttrList )
525 {
526     sal_Int32 nAttributeCount = _rxAttrList->getLength();
527 
528     sal_uInt16 nNamespace;
529     ::rtl::OUString sAttributeName;
530     const SvXMLNamespaceMap& rMap = GetImport().GetNamespaceMap();
531     for ( sal_Int16 i = 0; i < nAttributeCount; ++i )
532     {
533         nNamespace = rMap.GetKeyByAttrName( _rxAttrList->getNameByIndex( i ), &sAttributeName );
534         if  (   ( XML_NAMESPACE_FORM == nNamespace )
535             &&  ( token::IsXMLToken( sAttributeName, token::XML_PROPERTY_NAME ) )
536             )
537         {
538             m_sPropertyName = _rxAttrList->getValueByIndex( i );
539         }
540         else if (   ( XML_NAMESPACE_OFFICE == nNamespace )
541                 &&  ( token::IsXMLToken( sAttributeName, token::XML_VALUE_TYPE ) )
542                 )
543         {
544             m_sPropertyType = _rxAttrList->getValueByIndex( i );
545         }
546         else
547         {
548             OSL_ENSURE( false,
549                     ::rtl::OString( "OListPropertyContext::StartElement: unknown child element (\"")
550                 +=  ::rtl::OString( sAttributeName.getStr(), sAttributeName.getLength(), RTL_TEXTENCODING_ASCII_US )
551                 +=  ::rtl::OString( "\")!" ) );
552         }
553     }
554 }
555 
556 //---------------------------------------------------------------------
557 void OListPropertyContext::EndElement()
558 {
559     OSL_ENSURE( m_sPropertyName.getLength() && m_sPropertyType.getLength(),
560         "OListPropertyContext::EndElement: no property name or type!" );
561 
562     if ( !m_sPropertyName.getLength() || !m_sPropertyType.getLength() )
563         return;
564 
565     Sequence< Any > aListElements( m_aListValues.size() );
566     Any* pListElement = aListElements.getArray();
567     com::sun::star::uno::Type aType = PropertyConversion::xmlTypeToUnoType( m_sPropertyType );
568     for (   ::std::vector< ::rtl::OUString >::const_iterator values = m_aListValues.begin();
569             values != m_aListValues.end();
570             ++values, ++pListElement
571         )
572     {
573         *pListElement = PropertyConversion::convertString( GetImport(), aType, *values );
574     }
575 
576     PropertyValue aSequenceValue;
577     aSequenceValue.Name = m_sPropertyName;
578     aSequenceValue.Value <<= aListElements;
579 
580     m_xPropertyImporter->implPushBackGenericPropertyValue( aSequenceValue );
581 }
582 
583 //---------------------------------------------------------------------
584 SvXMLImportContext* OListPropertyContext::CreateChildContext( sal_uInt16 _nPrefix, const ::rtl::OUString& _rLocalName, const Reference< sax::XAttributeList >& /*_rxAttrList*/ )
585 {
586     if ( token::IsXMLToken( _rLocalName, token::XML_LIST_VALUE ) )
587     {
588         m_aListValues.resize( m_aListValues.size() + 1 );
589         return new OListValueContext( GetImport(), _nPrefix, _rLocalName, *m_aListValues.rbegin() );
590     }
591     else
592     {
593         OSL_ENSURE( sal_False,
594                 ::rtl::OString("OListPropertyContext::CreateChildContext: unknown child element (\"")
595             +=  ::rtl::OString(_rLocalName.getStr(), _rLocalName.getLength(), RTL_TEXTENCODING_ASCII_US)
596             +=  ::rtl::OString("\")!"));
597         return new SvXMLImportContext( GetImport(), _nPrefix, _rLocalName );
598     }
599 }
600 
601 //=====================================================================
602 //= OListValueContext
603 //=====================================================================
604 //---------------------------------------------------------------------
605 OListValueContext::OListValueContext( SvXMLImport& _rImport, sal_uInt16 _nPrefix, const ::rtl::OUString& _rName, ::rtl::OUString& _rListValueHolder )
606     :SvXMLImportContext( _rImport, _nPrefix, _rName )
607     ,m_rListValueHolder( _rListValueHolder )
608 {
609 }
610 
611 //---------------------------------------------------------------------
612 void OListValueContext::StartElement( const Reference< sax::XAttributeList >& _rxAttrList )
613 {
614     const sal_Int32 nAttributeCount = _rxAttrList->getLength();
615 
616     sal_uInt16 nNamespace;
617     ::rtl::OUString sAttributeName;
618     const SvXMLNamespaceMap& rMap = GetImport().GetNamespaceMap();
619     for ( sal_Int16 i = 0; i < nAttributeCount; ++i )
620     {
621         nNamespace = rMap.GetKeyByAttrName( _rxAttrList->getNameByIndex( i ), &sAttributeName );
622         if ( XML_NAMESPACE_OFFICE == nNamespace )
623         {
624             if  (   token::IsXMLToken( sAttributeName, token::XML_VALUE )
625                ||   token::IsXMLToken( sAttributeName, token::XML_STRING_VALUE )
626                ||   token::IsXMLToken( sAttributeName, token::XML_BOOLEAN_VALUE )
627                 )
628             {
629                 m_rListValueHolder = _rxAttrList->getValueByIndex( i );
630                 continue;
631             }
632         }
633 
634         OSL_ENSURE( false,
635                 ::rtl::OString( "OListValueContext::StartElement: unknown child element (\"")
636             +=  ::rtl::OString( sAttributeName.getStr(), sAttributeName.getLength(), RTL_TEXTENCODING_ASCII_US )
637             +=  ::rtl::OString( "\")!" ) );
638     }
639 }
640 
641 //.........................................................................
642 }   // namespace xmloff
643 //.........................................................................
644 
645