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