/src/libreoffice/xmloff/source/forms/propertyimport.cxx
Line | Count | Source |
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 <sal/config.h> |
21 | | |
22 | | #include <cmath> |
23 | | |
24 | | #include "propertyimport.hxx" |
25 | | |
26 | | #include <sax/tools/converter.hxx> |
27 | | |
28 | | #include <utility> |
29 | | #include <xmloff/xmlimp.hxx> |
30 | | #include <xmloff/xmluconv.hxx> |
31 | | #include <o3tl/temporary.hxx> |
32 | | #include <osl/diagnose.h> |
33 | | #include <sal/log.hxx> |
34 | | #include <comphelper/extract.hxx> |
35 | | #include <xmloff/xmlnamespace.hxx> |
36 | | #include <tools/date.hxx> |
37 | | #include <tools/time.hxx> |
38 | | #include <com/sun/star/util/Date.hpp> |
39 | | #include <com/sun/star/util/Time.hpp> |
40 | | #include <com/sun/star/util/DateTime.hpp> |
41 | | #include <unotools/datetime.hxx> |
42 | | #include <rtl/strbuf.hxx> |
43 | | |
44 | | using namespace ::xmloff::token; |
45 | | |
46 | | namespace xmloff |
47 | | { |
48 | | |
49 | | using namespace ::com::sun::star::uno; |
50 | | using namespace ::com::sun::star::beans; |
51 | | using namespace ::com::sun::star::xml; |
52 | | using ::com::sun::star::xml::sax::XFastAttributeList; |
53 | | |
54 | | // NO using namespace ...util !!! |
55 | | // need a tools Date/Time/DateTime below, which would conflict with the uno types then |
56 | | |
57 | 0 | #define TYPE_DATE 1 |
58 | 0 | #define TYPE_TIME 2 |
59 | 0 | #define TYPE_DATETIME 3 |
60 | | |
61 | | //= PropertyConversion |
62 | | namespace |
63 | | { |
64 | | css::util::Time lcl_getTime(double _nValue) |
65 | 0 | { |
66 | 0 | css::util::Time aTime; |
67 | 0 | sal_uInt64 nIntValue = static_cast<sal_uInt64>(_nValue * ::tools::Time::nanoSecPerDay); |
68 | 0 | aTime.NanoSeconds = nIntValue % ::tools::Time::nanoSecPerSec; |
69 | 0 | nIntValue /= ::tools::Time::nanoSecPerSec; |
70 | 0 | aTime.Seconds = nIntValue % ::tools::Time::secondPerMinute; |
71 | 0 | nIntValue /= ::tools::Time::secondPerMinute; |
72 | 0 | aTime.Minutes = nIntValue % ::tools::Time::minutePerHour; |
73 | 0 | nIntValue /= ::tools::Time::minutePerHour; |
74 | 0 | OSL_ENSURE(nIntValue < 24, "lcl_getTime: more than a day?"); |
75 | 0 | aTime.Hours = nIntValue; |
76 | |
|
77 | 0 | return aTime; |
78 | 0 | } |
79 | | |
80 | | css::util::Date lcl_getDate( double _nValue ) |
81 | 0 | { |
82 | 0 | Date aToolsDate(static_cast<sal_uInt32>(_nValue)); |
83 | 0 | css::util::Date aDate; |
84 | 0 | ::utl::typeConvert(aToolsDate, aDate); |
85 | 0 | return aDate; |
86 | 0 | } |
87 | | } |
88 | | |
89 | | namespace |
90 | | { |
91 | | |
92 | | Any convertAsEnum(bool bEnumAsInt, const css::uno::Type& _rExpectedType, |
93 | | std::u16string_view _rReadCharacters, const SvXMLEnumMapEntry<sal_uInt16>* _pEnumMap) |
94 | 0 | { |
95 | 0 | Any aReturn; |
96 | |
|
97 | 0 | sal_uInt16 nEnumValue(0); |
98 | 0 | bool bSuccess = SvXMLUnitConverter::convertEnum(nEnumValue, _rReadCharacters, _pEnumMap); |
99 | 0 | OSL_ENSURE(bSuccess, "PropertyConversion::convertString: could not convert to an enum value!"); |
100 | |
|
101 | 0 | if (bEnumAsInt) |
102 | 0 | { |
103 | 0 | if (TypeClass_SHORT == _rExpectedType.getTypeClass()) |
104 | 0 | aReturn <<= static_cast<sal_Int16>(nEnumValue); |
105 | 0 | else |
106 | 0 | aReturn <<= static_cast<sal_Int32>(nEnumValue); |
107 | 0 | } |
108 | 0 | else |
109 | 0 | aReturn = ::cppu::int2enum(static_cast<sal_Int32>(nEnumValue), _rExpectedType); |
110 | |
|
111 | 0 | return aReturn; |
112 | 0 | } |
113 | | |
114 | | } |
115 | | |
116 | | Any PropertyConversion::convertString( const css::uno::Type& _rExpectedType, |
117 | | const OUString& _rReadCharacters, const SvXMLEnumMapEntry<sal_uInt16>* _pEnumMap, const bool _bInvertBoolean ) |
118 | 0 | { |
119 | 0 | Any aReturn; |
120 | 0 | switch (_rExpectedType.getTypeClass()) |
121 | 0 | { |
122 | 0 | case TypeClass_BOOLEAN: // sal_Bool |
123 | 0 | { |
124 | 0 | bool bValue; |
125 | 0 | bool bSuccess = |
126 | 0 | ::sax::Converter::convertBool(bValue, _rReadCharacters); |
127 | 0 | OSL_ENSURE(bSuccess, |
128 | 0 | OStringBuffer("PropertyConversion::convertString: could not convert \"" + |
129 | 0 | OUStringToOString(_rReadCharacters, RTL_TEXTENCODING_ASCII_US) + |
130 | 0 | "\" into a boolean!").getStr()); |
131 | 0 | aReturn <<= (_bInvertBoolean ? !bValue : bValue); |
132 | 0 | } |
133 | 0 | break; |
134 | 0 | case TypeClass_SHORT: // sal_Int16 |
135 | 0 | { |
136 | 0 | if (!_pEnumMap) |
137 | 0 | { // it's a real int16 property |
138 | 0 | sal_Int32 nValue(0); |
139 | 0 | bool bSuccess = |
140 | 0 | ::sax::Converter::convertNumber(nValue, _rReadCharacters, SAL_MIN_INT16, SAL_MAX_INT16); |
141 | 0 | OSL_ENSURE(bSuccess, |
142 | 0 | OStringBuffer("PropertyConversion::convertString: could not convert \"" + |
143 | 0 | OUStringToOString(_rReadCharacters, RTL_TEXTENCODING_ASCII_US) + |
144 | 0 | "\" into a sal_Int16!").getStr()); |
145 | 0 | aReturn <<= static_cast<sal_Int16>(nValue); |
146 | 0 | break; |
147 | 0 | } |
148 | 0 | aReturn = convertAsEnum(true, _rExpectedType, _rReadCharacters, _pEnumMap); |
149 | 0 | } |
150 | 0 | break; |
151 | 0 | case TypeClass_LONG: // sal_Int32 |
152 | 0 | { |
153 | 0 | if (!_pEnumMap) |
154 | 0 | { // it's a real int32 property |
155 | 0 | sal_Int32 nValue(0); |
156 | 0 | bool bSuccess = |
157 | 0 | ::sax::Converter::convertNumber(nValue, _rReadCharacters); |
158 | 0 | OSL_ENSURE(bSuccess, |
159 | 0 | OStringBuffer("PropertyConversion::convertString: could not convert \"" + |
160 | 0 | OUStringToOString(_rReadCharacters, RTL_TEXTENCODING_ASCII_US) + |
161 | 0 | "\" into a sal_Int32!").getStr()); |
162 | 0 | aReturn <<= nValue; |
163 | 0 | break; |
164 | 0 | } |
165 | 0 | aReturn = convertAsEnum(true, _rExpectedType, _rReadCharacters, _pEnumMap); |
166 | 0 | } |
167 | 0 | break; |
168 | 0 | case TypeClass_ENUM: |
169 | 0 | { |
170 | 0 | aReturn = convertAsEnum(false, _rExpectedType, _rReadCharacters, _pEnumMap); |
171 | 0 | } |
172 | 0 | break; |
173 | 0 | case TypeClass_HYPER: |
174 | 0 | { |
175 | 0 | OSL_FAIL("PropertyConversion::convertString: 64-bit integers not implemented yet!"); |
176 | 0 | } |
177 | 0 | break; |
178 | 0 | case TypeClass_DOUBLE: |
179 | 0 | { |
180 | 0 | double nValue; |
181 | 0 | bool bSuccess = |
182 | 0 | ::sax::Converter::convertDouble(nValue, _rReadCharacters); |
183 | 0 | OSL_ENSURE(bSuccess, |
184 | 0 | OStringBuffer(OString::Concat("PropertyConversion::convertString: could not convert \"") + |
185 | 0 | OUStringToOString(_rReadCharacters, RTL_TEXTENCODING_ASCII_US) + |
186 | 0 | "\" into a double!").getStr()); |
187 | 0 | aReturn <<= nValue; |
188 | 0 | } |
189 | 0 | break; |
190 | 0 | case TypeClass_STRING: |
191 | 0 | aReturn <<= _rReadCharacters; |
192 | 0 | break; |
193 | 0 | case TypeClass_STRUCT: |
194 | 0 | { |
195 | 0 | sal_Int32 nType = 0; |
196 | 0 | if ( _rExpectedType.equals( ::cppu::UnoType< css::util::Date >::get() ) ) |
197 | 0 | nType = TYPE_DATE; |
198 | 0 | else if ( _rExpectedType.equals( ::cppu::UnoType< css::util::Time >::get() ) ) |
199 | 0 | nType = TYPE_TIME; |
200 | 0 | else if ( _rExpectedType.equals( ::cppu::UnoType< css::util::DateTime >::get() ) ) |
201 | 0 | nType = TYPE_DATETIME; |
202 | |
|
203 | 0 | if ( nType ) |
204 | 0 | { |
205 | | // first extract the double |
206 | 0 | double nValue = 0; |
207 | 0 | bool bSuccess = |
208 | 0 | ::sax::Converter::convertDouble(nValue, _rReadCharacters); |
209 | 0 | OSL_ENSURE(bSuccess, |
210 | 0 | OStringBuffer("PropertyConversion::convertString: could not convert \"" + |
211 | 0 | OUStringToOString(_rReadCharacters, RTL_TEXTENCODING_ASCII_US) + |
212 | 0 | "\" into a double!").getStr()); |
213 | | |
214 | | // then convert it into the target type |
215 | 0 | switch (nType) |
216 | 0 | { |
217 | 0 | case TYPE_DATE: |
218 | 0 | { |
219 | 0 | OSL_ENSURE(std::modf(nValue, &o3tl::temporary(double())) == 0, |
220 | 0 | "PropertyConversion::convertString: a Date value with a fractional part?"); |
221 | 0 | aReturn <<= lcl_getDate(nValue); |
222 | 0 | } |
223 | 0 | break; |
224 | 0 | case TYPE_TIME: |
225 | 0 | { |
226 | 0 | OSL_ENSURE((static_cast<sal_uInt32>(nValue)) == 0, |
227 | 0 | "PropertyConversion::convertString: a tools::Time value with more than a fractional part?"); |
228 | 0 | aReturn <<= lcl_getTime(nValue); |
229 | 0 | } |
230 | 0 | break; |
231 | 0 | case TYPE_DATETIME: |
232 | 0 | { |
233 | 0 | css::util::Time aTime = lcl_getTime(nValue); |
234 | 0 | css::util::Date aDate = lcl_getDate(nValue); |
235 | |
|
236 | 0 | css::util::DateTime aDateTime; |
237 | 0 | aDateTime.NanoSeconds = aTime.NanoSeconds; |
238 | 0 | aDateTime.Seconds = aTime.Seconds; |
239 | 0 | aDateTime.Minutes = aTime.Minutes; |
240 | 0 | aDateTime.Hours = aTime.Hours; |
241 | 0 | aDateTime.Day = aDate.Day; |
242 | 0 | aDateTime.Month = aDate.Month; |
243 | 0 | aDateTime.Year = aDate.Year; |
244 | 0 | aReturn <<= aDateTime; |
245 | 0 | } |
246 | 0 | break; |
247 | 0 | } |
248 | 0 | } |
249 | 0 | else |
250 | 0 | OSL_FAIL("PropertyConversion::convertString: unsupported property type!"); |
251 | 0 | } |
252 | 0 | break; |
253 | 0 | default: |
254 | 0 | OSL_FAIL("PropertyConversion::convertString: invalid type class!"); |
255 | 0 | } |
256 | | |
257 | 0 | return aReturn; |
258 | 0 | } |
259 | | |
260 | | Type PropertyConversion::xmlTypeToUnoType( const OUString& _rType ) |
261 | 0 | { |
262 | 0 | Type aUnoType( cppu::UnoType<void>::get() ); |
263 | |
|
264 | 0 | static std::map< OUString, css::uno::Type > s_aTypeNameMap |
265 | 0 | { |
266 | 0 | { token::GetXMLToken( token::XML_BOOLEAN ) , cppu::UnoType<bool>::get()}, |
267 | | // Not a copy paste error, quotation from: |
268 | | // http://nabble.documentfoundation.org/Question-unoType-for-getXmlToken-dbaccess-reportdesign-module-tp4109071p4109116.html |
269 | | // all numeric types (including the UNO double) |
270 | | // consistently map to XML_FLOAT, so taking the extra precision from the |
271 | | // C++ type "float" to "double" makes absolute sense |
272 | 0 | { token::GetXMLToken( token::XML_FLOAT ) , ::cppu::UnoType<double>::get()}, |
273 | 0 | { token::GetXMLToken( token::XML_STRING ) , ::cppu::UnoType<OUString>::get()}, |
274 | 0 | { token::GetXMLToken( token::XML_VOID ) , cppu::UnoType<void>::get() }, |
275 | 0 | }; |
276 | |
|
277 | 0 | const std::map< OUString, css::uno::Type >::iterator aTypePos = s_aTypeNameMap.find( _rType ); |
278 | 0 | OSL_ENSURE( s_aTypeNameMap.end() != aTypePos, "PropertyConversion::xmlTypeToUnoType: invalid property name!" ); |
279 | 0 | if ( s_aTypeNameMap.end() != aTypePos ) |
280 | 0 | aUnoType = aTypePos->second; |
281 | |
|
282 | 0 | return aUnoType; |
283 | 0 | } |
284 | | |
285 | | //= OPropertyImport |
286 | | OPropertyImport::OPropertyImport(OFormLayerXMLImport_Impl& _rImport) |
287 | 0 | :SvXMLImportContext(_rImport.getGlobalContext()) |
288 | 0 | ,m_rContext(_rImport) |
289 | 0 | ,m_bTrackAttributes(false) |
290 | 0 | { |
291 | 0 | } |
292 | | |
293 | | css::uno::Reference< css::xml::sax::XFastContextHandler > OPropertyImport::createFastChildContext( |
294 | | sal_Int32 nElement, |
295 | | const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ ) |
296 | 0 | { |
297 | 0 | if( (nElement & TOKEN_MASK) == token::XML_PROPERTIES ) |
298 | 0 | { |
299 | 0 | return new OPropertyElementsContext( m_rContext.getGlobalContext(), this); |
300 | 0 | } |
301 | 0 | else |
302 | 0 | SAL_WARN("xmloff", "unknown element " << SvXMLImport::getPrefixAndNameFromToken(nElement)); |
303 | 0 | return nullptr; |
304 | 0 | } |
305 | | |
306 | | void OPropertyImport::startFastElement(sal_Int32 /*nElement*/, const Reference< XFastAttributeList >& xAttrList) |
307 | 0 | { |
308 | | |
309 | | // assume the 'worst' case: all attributes describe properties. This should save our property array |
310 | | // some reallocs |
311 | 0 | m_aValues.reserve(sax_fastparser::castToFastAttributeList(xAttrList).size()); |
312 | |
|
313 | 0 | for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) |
314 | 0 | { |
315 | 0 | handleAttribute(aIter.getToken(), aIter.toString()); |
316 | |
|
317 | 0 | if (m_bTrackAttributes) |
318 | 0 | m_aEncounteredAttributes.insert(aIter.getToken() & TOKEN_MASK); |
319 | 0 | } |
320 | | |
321 | | // TODO: create PropertyValues for all the attributes which were not present, because they were implied |
322 | | // this is necessary as soon as we have properties where the XML default is different from the property |
323 | | // default |
324 | 0 | } |
325 | | |
326 | | bool OPropertyImport::encounteredAttribute(sal_Int32 nAttributeToken) const |
327 | 0 | { |
328 | 0 | OSL_ENSURE(m_bTrackAttributes, "OPropertyImport::encounteredAttribute: attribute tracking not enabled!"); |
329 | 0 | return m_aEncounteredAttributes.end() != m_aEncounteredAttributes.find(nAttributeToken & TOKEN_MASK); |
330 | 0 | } |
331 | | |
332 | | void OPropertyImport::characters(const OUString& _rChars ) |
333 | 0 | { |
334 | | // ignore them (should be whitespace only) |
335 | 0 | OSL_ENSURE(o3tl::trim(_rChars).empty(), "OPropertyImport::Characters: non-whitespace characters!"); |
336 | 0 | } |
337 | | |
338 | | bool OPropertyImport::handleAttribute(sal_Int32 nAttributeToken, const OUString& _rValue) |
339 | 0 | { |
340 | 0 | const OAttribute2Property::AttributeAssignment* pProperty = m_rContext.getAttributeMap().getAttributeTranslation(nAttributeToken & TOKEN_MASK); |
341 | 0 | if (pProperty) |
342 | 0 | { |
343 | | // create and store a new PropertyValue |
344 | 0 | PropertyValue aNewValue; |
345 | 0 | aNewValue.Name = pProperty->sPropertyName; |
346 | | |
347 | | // convert the value string into the target type |
348 | 0 | if ((nAttributeToken & TOKEN_MASK) == token::XML_HREF) |
349 | 0 | { |
350 | 0 | aNewValue.Value <<= m_rContext.getGlobalContext().GetAbsoluteReference(_rValue); |
351 | 0 | } |
352 | 0 | else |
353 | 0 | { |
354 | 0 | aNewValue.Value = PropertyConversion::convertString( |
355 | 0 | pProperty->aPropertyType, _rValue, pProperty->pEnumMap, |
356 | 0 | pProperty->bInverseSemantics); |
357 | 0 | } |
358 | 0 | implPushBackPropertyValue( aNewValue ); |
359 | 0 | return true; |
360 | 0 | } |
361 | 0 | if ((nAttributeToken & TOKEN_MASK) != token::XML_TYPE) // xlink:type is valid but ignored for <form:form> |
362 | 0 | { |
363 | 0 | SAL_WARN( "xmloff", "OPropertyImport::handleAttribute: Can't handle " |
364 | 0 | << SvXMLImport::getPrefixAndNameFromToken(nAttributeToken) << "=" << _rValue ); |
365 | 0 | return false; |
366 | 0 | } |
367 | 0 | return true; |
368 | 0 | } |
369 | | |
370 | | //= OPropertyElementsContext |
371 | | OPropertyElementsContext::OPropertyElementsContext(SvXMLImport& _rImport, |
372 | | OPropertyImportRef _xPropertyImporter) |
373 | 0 | :SvXMLImportContext(_rImport) |
374 | 0 | ,m_xPropertyImporter(std::move(_xPropertyImporter)) |
375 | 0 | { |
376 | 0 | } |
377 | | |
378 | | css::uno::Reference< css::xml::sax::XFastContextHandler > OPropertyElementsContext::createFastChildContext( |
379 | | sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& ) |
380 | 0 | { |
381 | 0 | if( (nElement & TOKEN_MASK) == XML_PROPERTY ) |
382 | 0 | { |
383 | 0 | return new OSinglePropertyContext(GetImport(), m_xPropertyImporter); |
384 | 0 | } |
385 | 0 | else if( (nElement & TOKEN_MASK) == XML_LIST_PROPERTY ) |
386 | 0 | { |
387 | 0 | return new OListPropertyContext( GetImport(), m_xPropertyImporter ); |
388 | 0 | } |
389 | 0 | return nullptr; |
390 | 0 | } |
391 | | |
392 | | #if OSL_DEBUG_LEVEL > 0 |
393 | | void OPropertyElementsContext::startFastElement( |
394 | | sal_Int32 /*nElement*/, |
395 | | const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) |
396 | | { |
397 | | OSL_ENSURE(0 == xAttrList->getFastAttributes().getLength(), "OPropertyElementsContext::StartElement: the form:properties element should not have attributes!"); |
398 | | } |
399 | | |
400 | | void OPropertyElementsContext::characters(const OUString& _rChars) |
401 | | { |
402 | | OSL_ENSURE(o3tl::trim(_rChars).empty(), "OPropertyElementsContext::Characters: non-whitespace characters detected!"); |
403 | | } |
404 | | #endif |
405 | | |
406 | | //= OSinglePropertyContext |
407 | | OSinglePropertyContext::OSinglePropertyContext(SvXMLImport& _rImport, |
408 | | OPropertyImportRef _xPropertyImporter) |
409 | 0 | :SvXMLImportContext(_rImport) |
410 | 0 | ,m_xPropertyImporter(std::move(_xPropertyImporter)) |
411 | 0 | { |
412 | 0 | } |
413 | | |
414 | | void OSinglePropertyContext::startFastElement( |
415 | | sal_Int32 /*nElement*/, |
416 | | const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) |
417 | 0 | { |
418 | 0 | css::beans::PropertyValue aPropValue; // the property the instance imports currently |
419 | 0 | css::uno::Type aPropType; // the type of the property the instance imports currently |
420 | |
|
421 | 0 | OUString sType, sValue; |
422 | 0 | for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) |
423 | 0 | { |
424 | 0 | switch (aIter.getToken()) |
425 | 0 | { |
426 | 0 | case XML_ELEMENT(FORM, XML_PROPERTY_NAME): |
427 | 0 | aPropValue.Name = aIter.toString(); |
428 | 0 | break; |
429 | 0 | case XML_ELEMENT(OFFICE, XML_VALUE_TYPE): |
430 | 0 | sType = aIter.toString(); |
431 | 0 | break; |
432 | 0 | case XML_ELEMENT(OFFICE, XML_VALUE): |
433 | 0 | case XML_ELEMENT(OFFICE, XML_BOOLEAN_VALUE): |
434 | 0 | case XML_ELEMENT(OFFICE, XML_STRING_VALUE): |
435 | 0 | sValue = aIter.toString(); |
436 | 0 | break; |
437 | 0 | default: |
438 | 0 | XMLOFF_WARN_UNKNOWN("xmloff", aIter); |
439 | 0 | } |
440 | 0 | } |
441 | | |
442 | | // the name of the property |
443 | 0 | OSL_ENSURE(!aPropValue.Name.isEmpty(), "OSinglePropertyContext::StartElement: invalid property name!"); |
444 | | |
445 | | // needs to be translated into a css::uno::Type |
446 | 0 | aPropType = PropertyConversion::xmlTypeToUnoType( sType ); |
447 | 0 | if( TypeClass_VOID == aPropType.getTypeClass() ) |
448 | 0 | { |
449 | 0 | aPropValue.Value = Any(); |
450 | 0 | } |
451 | 0 | else |
452 | 0 | { |
453 | 0 | aPropValue.Value = |
454 | 0 | PropertyConversion::convertString(aPropType, |
455 | 0 | sValue); |
456 | 0 | } |
457 | | |
458 | | // now that we finally have our property value, add it to our parent object |
459 | 0 | if( !aPropValue.Name.isEmpty() ) |
460 | 0 | m_xPropertyImporter->implPushBackGenericPropertyValue(aPropValue); |
461 | 0 | } |
462 | | |
463 | | //= OListPropertyContext |
464 | | OListPropertyContext::OListPropertyContext( SvXMLImport& _rImport, |
465 | | OPropertyImportRef _rPropertyImporter ) |
466 | 0 | :SvXMLImportContext( _rImport ) |
467 | 0 | ,m_xPropertyImporter(std::move( _rPropertyImporter )) |
468 | 0 | { |
469 | 0 | } |
470 | | |
471 | | void OListPropertyContext::startFastElement( |
472 | | sal_Int32 /*nElement*/, |
473 | | const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) |
474 | 0 | { |
475 | 0 | for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) |
476 | 0 | { |
477 | 0 | switch (aIter.getToken()) |
478 | 0 | { |
479 | 0 | case XML_ELEMENT(FORM, XML_PROPERTY_NAME): |
480 | 0 | m_sPropertyName = aIter.toString(); |
481 | 0 | break; |
482 | 0 | case XML_ELEMENT(OFFICE, XML_VALUE_TYPE): |
483 | 0 | m_sPropertyType = aIter.toString(); |
484 | 0 | break; |
485 | 0 | default: |
486 | 0 | XMLOFF_WARN_UNKNOWN("xmloff", aIter); |
487 | 0 | } |
488 | 0 | } |
489 | 0 | } |
490 | | |
491 | | void OListPropertyContext::endFastElement(sal_Int32 ) |
492 | 0 | { |
493 | 0 | OSL_ENSURE( !m_sPropertyName.isEmpty() && !m_sPropertyType.isEmpty(), |
494 | 0 | "OListPropertyContext::EndElement: no property name or type!" ); |
495 | |
|
496 | 0 | if ( m_sPropertyName.isEmpty() || m_sPropertyType.isEmpty() ) |
497 | 0 | return; |
498 | | |
499 | 0 | Sequence< Any > aListElements( m_aListValues.size() ); |
500 | 0 | Any* pListElement = aListElements.getArray(); |
501 | 0 | css::uno::Type aType = PropertyConversion::xmlTypeToUnoType( m_sPropertyType ); |
502 | 0 | for ( const auto& rListValue : m_aListValues ) |
503 | 0 | { |
504 | 0 | *pListElement = PropertyConversion::convertString( aType, rListValue ); |
505 | 0 | ++pListElement; |
506 | 0 | } |
507 | |
|
508 | 0 | PropertyValue aSequenceValue; |
509 | 0 | aSequenceValue.Name = m_sPropertyName; |
510 | 0 | aSequenceValue.Value <<= aListElements; |
511 | |
|
512 | 0 | m_xPropertyImporter->implPushBackGenericPropertyValue( aSequenceValue ); |
513 | 0 | } |
514 | | |
515 | | css::uno::Reference< css::xml::sax::XFastContextHandler > OListPropertyContext::createFastChildContext( |
516 | | sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& ) |
517 | 0 | { |
518 | 0 | if ( (nElement & TOKEN_MASK) == XML_LIST_VALUE ) |
519 | 0 | { |
520 | 0 | m_aListValues.emplace_back(); |
521 | 0 | return new OListValueContext( GetImport(), *m_aListValues.rbegin() ); |
522 | 0 | } |
523 | 0 | return nullptr; |
524 | 0 | } |
525 | | |
526 | | //= OListValueContext |
527 | | OListValueContext::OListValueContext( SvXMLImport& _rImport, OUString& _rListValueHolder ) |
528 | 0 | :SvXMLImportContext( _rImport ) |
529 | 0 | ,m_rListValueHolder( _rListValueHolder ) |
530 | 0 | { |
531 | 0 | } |
532 | | |
533 | | void OListValueContext::startFastElement( |
534 | | sal_Int32 /*nElement*/, |
535 | | const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) |
536 | 0 | { |
537 | 0 | for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) |
538 | 0 | { |
539 | 0 | switch(aIter.getToken()) |
540 | 0 | { |
541 | 0 | case XML_ELEMENT(OFFICE, XML_VALUE): |
542 | 0 | case XML_ELEMENT(OFFICE, XML_STRING_VALUE): |
543 | 0 | case XML_ELEMENT(OFFICE, XML_BOOLEAN_VALUE): |
544 | 0 | m_rListValueHolder = aIter.toString(); |
545 | 0 | break; |
546 | 0 | default: |
547 | 0 | XMLOFF_WARN_UNKNOWN("xmloff", aIter); |
548 | 0 | } |
549 | 0 | } |
550 | 0 | } |
551 | | |
552 | | } // namespace xmloff |
553 | | |
554 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |