LibreOffice Module reportdesign (master)  1
xmlControlProperty.cxx
Go to the documentation of this file.
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 #include <map>
24 
25 #include "xmlControlProperty.hxx"
26 
27 #include <o3tl/temporary.hxx>
28 #include <rtl/strbuf.hxx>
29 #include <sax/tools/converter.hxx>
30 #include "xmlfilter.hxx"
31 #include <xmloff/xmltoken.hxx>
32 #include <xmloff/xmlnamespace.hxx>
34 #include "xmlEnums.hxx"
35 #include <tools/date.hxx>
36 #include <unotools/datetime.hxx>
37 #include <com/sun/star/util/DateTime.hpp>
38 #include <rtl/math.hxx>
39 #include <osl/diagnose.h>
40 #include <sal/log.hxx>
41 
42 #define TYPE_DATE 1
43 #define TYPE_TIME 2
44 #define TYPE_DATETIME 3
45 
46 namespace rptxml
47 {
48  using namespace ::com::sun::star::uno;
49  using namespace ::com::sun::star::beans;
50  using namespace ::com::sun::star::xml::sax;
51 
53  ,const Reference< XFastAttributeList > & _xAttrList
54  ,const Reference< XPropertySet >& _xControl
55  ,OXMLControlProperty* _pContainer) :
56  SvXMLImportContext( rImport )
57  ,m_xControl(_xControl)
58  ,m_pContainer(_pContainer)
59  ,m_bIsList(false)
60 {
61  m_aPropType = cppu::UnoType<void>::get();
62 
63  OSL_ENSURE(m_xControl.is(),"Control is NULL!");
64 
65  for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
66  {
67  switch( aIter.getToken() )
68  {
70  m_bIsList = aIter.toView() == "true";
71  break;
72  case XML_ELEMENT(OOO, XML_VALUE_TYPE):
73  {
74  // needs to be translated into a css::uno::Type
75  static std::map< OUString, css::uno::Type > const s_aTypeNameMap
76  {
78  // Not a copy paste error, see comment xmloff/source/forms/propertyimport.cxx lines 244-248
87  };
88 
89  const std::map< OUString, css::uno::Type >::const_iterator aTypePos = s_aTypeNameMap.find(aIter.toString());
90  OSL_ENSURE(s_aTypeNameMap.end() != aTypePos, "OXMLControlProperty::OXMLControlProperty: invalid type!");
91  if (s_aTypeNameMap.end() != aTypePos)
92  m_aPropType = aTypePos->second;
93  }
94  break;
96  m_aSetting.Name = aIter.toString();
97  break;
98  default:
99  XMLOFF_WARN_UNKNOWN("reportdesign", aIter);
100  break;
101  }
102  }
103 
104 }
105 
106 
108 {
109 }
110 
111 css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLControlProperty::createFastChildContext(
112  sal_Int32 nElement,
113  const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
114 {
115  css::uno::Reference< css::xml::sax::XFastContextHandler > xContext;
116  ORptFilter& rImport = GetOwnImport();
117 
118  switch( nElement )
119  {
122  xContext = new OXMLControlProperty( rImport,xAttrList,m_xControl);
123  break;
124  case XML_ELEMENT(OOO, XML_VALUE):
126  xContext = new OXMLControlProperty( rImport,xAttrList,m_xControl,this );
127  break;
128  default:
129  break;
130  }
131 
132  return xContext;
133 }
134 
136 {
137  if ( m_pContainer )
138  m_pContainer->addValue(m_aCharBuffer.makeStringAndClear());
139  if ( m_aSetting.Name.isEmpty() || !m_xControl.is() )
140  return;
141 
142  if ( m_bIsList && !m_aSequence.hasElements() )
143  m_aSetting.Value <<= m_aSequence;
144  try
145  {
146  m_xControl->setPropertyValue(m_aSetting.Name,m_aSetting.Value);
147  }
148  catch(const Exception&)
149  {
150  OSL_FAIL("Unknown property found!");
151  }
152 }
153 
154 void OXMLControlProperty::characters( const OUString& rChars )
155 {
156  m_aCharBuffer.append(rChars);
157 }
158 
159 void OXMLControlProperty::addValue(const OUString& _sValue)
160 {
161  Any aValue;
162  if( TypeClass_VOID != m_aPropType.getTypeClass() )
163  aValue = convertString(m_aPropType, _sValue);
164 
165  if ( !m_bIsList )
166  m_aSetting.Value = aValue;
167  else
168  {
169  sal_Int32 nPos = m_aSequence.getLength();
170  m_aSequence.realloc(nPos+1);
171  m_aSequence[nPos] = aValue;
172  }
173 }
174 
175 ORptFilter& OXMLControlProperty::GetOwnImport()
176 {
177  return static_cast<ORptFilter&>(GetImport());
178 }
179 
180 Any OXMLControlProperty::convertString(const css::uno::Type& _rExpectedType, const OUString& _rReadCharacters)
181 {
182  Any aReturn;
183  switch (_rExpectedType.getTypeClass())
184  {
185  case TypeClass_BOOLEAN: // sal_Bool
186  {
187  bool bValue(false);
188  bool bSuccess =
189  ::sax::Converter::convertBool(bValue, _rReadCharacters);
190  OSL_ENSURE(bSuccess,
191  OStringBuffer("OXMLControlProperty::convertString: could not convert \"" +
192  OUStringToOString(_rReadCharacters, RTL_TEXTENCODING_ASCII_US) +
193  "\" into a boolean!").getStr());
194  aReturn <<= bValue;
195  }
196  break;
197  case TypeClass_SHORT: // sal_Int16
198  case TypeClass_LONG: // sal_Int32
199  { // it's a real int32/16 property
200  sal_Int32 nValue(0);
201  bool bSuccess =
202  ::sax::Converter::convertNumber(nValue, _rReadCharacters);
203  OSL_ENSURE(bSuccess,
204  OStringBuffer("OXMLControlProperty::convertString: could not convert \"" +
205  OUStringToOString(_rReadCharacters, RTL_TEXTENCODING_ASCII_US) +
206  "\" into an integer!").getStr());
207  if (TypeClass_SHORT == _rExpectedType.getTypeClass())
208  aReturn <<= static_cast<sal_Int16>(nValue);
209  else
210  aReturn <<= nValue;
211  break;
212  }
213  case TypeClass_HYPER:
214  {
215  OSL_FAIL("OXMLControlProperty::convertString: 64-bit integers not implemented yet!");
216  }
217  break;
218  case TypeClass_DOUBLE:
219  {
220  double nValue = 0.0;
221  bool bSuccess =
222  ::sax::Converter::convertDouble(nValue, _rReadCharacters);
223  OSL_ENSURE(bSuccess,
224  OStringBuffer("OXMLControlProperty::convertString: could not convert \"" +
225  OUStringToOString(_rReadCharacters, RTL_TEXTENCODING_ASCII_US) +
226  "\" into a double!").getStr());
227  aReturn <<= nValue;
228  }
229  break;
230  case TypeClass_STRING:
231  aReturn <<= _rReadCharacters;
232  break;
233  case TypeClass_STRUCT:
234  {
235  // recognized structs:
236  static css::uno::Type s_aDateType = ::cppu::UnoType<css::util::Date>::get();
237  static css::uno::Type s_aTimeType = ::cppu::UnoType<css::util::Time>::get();
238  static css::uno::Type s_aDateTimeType = ::cppu::UnoType<css::util::DateTime>::get();
239  sal_Int32 nType = 0;
240  if ( _rExpectedType.equals(s_aDateType) )
241  nType = TYPE_DATE;
242  else if ( _rExpectedType.equals(s_aTimeType) )
243  nType = TYPE_TIME;
244  else if ( _rExpectedType.equals(s_aDateTimeType) )
245  nType = TYPE_DATETIME;
246  if ( nType )
247  {
248  // first extract the double
249  double nValue = 0;
250  bool bSuccess =
251  ::sax::Converter::convertDouble(nValue, _rReadCharacters);
252  OSL_ENSURE(bSuccess,
253  OStringBuffer("OPropertyImport::convertString: could not convert \"" +
254  OUStringToOString(_rReadCharacters, RTL_TEXTENCODING_ASCII_US) +
255  "\" into a double!").getStr());
256 
257  // then convert it into the target type
258  switch (nType)
259  {
260  case TYPE_DATE:
261  {
262  OSL_ENSURE(std::modf(nValue, &o3tl::temporary(double())) == 0,
263  "OPropertyImport::convertString: a Date value with a fractional part?");
264  aReturn <<= implGetDate(nValue);
265  }
266  break;
267  case TYPE_TIME:
268  {
269  OSL_ENSURE((static_cast<sal_uInt32>(nValue)) == 0,
270  "OPropertyImport::convertString: a tools::Time value with more than a fractional part?");
271  aReturn <<= implGetTime(nValue);
272  }
273  break;
274  case TYPE_DATETIME:
275  {
276  css::util::Time aTime = implGetTime(nValue);
277  css::util::Date aDate = implGetDate(nValue);
278 
279  css::util::DateTime aDateTime;
280  aDateTime.NanoSeconds = aTime.NanoSeconds;
281  aDateTime.Seconds = aTime.Seconds;
282  aDateTime.Minutes = aTime.Minutes;
283  aDateTime.Hours = aTime.Hours;
284  aDateTime.Day = aDate.Day;
285  aDateTime.Month = aDate.Month;
286  aDateTime.Year = aDate.Year;
287  aReturn <<= aDateTime;
288  }
289  break;
290  default:
291  break;
292  }
293  }
294  else
295  OSL_FAIL("OPropertyImport::convertString: unsupported property type!");
296  }
297  break;
298  default:
299  OSL_FAIL("OXMLControlProperty::convertString: invalid type class!");
300  }
301 
302  return aReturn;
303 }
304 
305 css::util::Time OXMLControlProperty::implGetTime(double _nValue)
306 {
307  css::util::Time aTime;
308  sal_uInt64 nIntValue = ::rtl::math::round(_nValue * 86400000000000.0);
309  aTime.NanoSeconds = static_cast<sal_uInt16>( nIntValue % 1000000000 );
310  nIntValue /= 1000000000;
311  aTime.Seconds = static_cast<sal_uInt16>( nIntValue % 60 );
312  nIntValue /= 60;
313  aTime.Minutes = static_cast<sal_uInt16>( nIntValue % 60 );
314  nIntValue /= 60;
315  OSL_ENSURE(nIntValue < 24, "OPropertyImport::implGetTime: more than a day?");
316  aTime.Hours = static_cast< sal_uInt16 >( nIntValue );
317 
318  return aTime;
319 }
320 
321 
322 css::util::Date OXMLControlProperty::implGetDate(double _nValue)
323 {
324  Date aToolsDate(static_cast<sal_uInt32>(_nValue));
325  css::util::Date aDate;
326  ::utl::typeConvert(aToolsDate, aDate);
327  return aDate;
328 }
329 
330 } // namespace rptxml
331 
332 
333 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
XML_VALUE_TYPE
XML_STRING
Reference< XControl > m_xControl
css::beans::PropertyValue m_aSetting
css::uno::Sequence< css::uno::Any > m_aSequence
XML_DOUBLE
#define TYPE_DATE
XML_VALUE
XML_SHORT
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
css::uno::Reference< css::beans::XPropertySet > m_xControl
static void convertDouble(OUStringBuffer &rBuffer, double fNumber, bool bWriteUnits, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
XML_LIST_PROPERTY
OString convertString(OUString const &string)
#define XMLOFF_WARN_UNKNOWN(area, rIter)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
XML_INT
void Increment(sal_Int32 nInc=1)
XML_VOID
XML_FLOAT
XML_DATE
XML_TIME
ProgressBarHelper * GetProgressBarHelper()
XML_PROPERTY_NAME
css::uno::Type const & get()
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
static bool convertBool(bool &rBool, std::u16string_view rString)
constexpr T & temporary(T &&x)
#define TYPE_DATETIME
void addValue(const OUString &_sValue)
adds value to property
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
virtual ~OXMLControlProperty() override
FORM
#define XML_ELEMENT(prefix, name)
#define PROGRESS_BAR_STEP
Definition: xmlEnums.hxx:22
QPRO_FUNC_TYPE nType
OXMLControlProperty(const OXMLControlProperty &)=delete
OXMLControlProperty * m_pContainer
XML_BOOLEAN
#define TYPE_TIME
sal_uInt16 nPos
sal_Int16 nValue
static bool convertNumber(sal_Int32 &rValue, std::u16string_view aString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32)