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