/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include "xmlControlProperty.hxx" #include #include #include #include "xmlfilter.hxx" #include #include #include #include "xmlEnums.hxx" #include #include #include #include #include #include #define TYPE_DATE 1 #define TYPE_TIME 2 #define TYPE_DATETIME 3 namespace rptxml { using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::xml::sax; OXMLControlProperty::OXMLControlProperty( ORptFilter& rImport ,const Reference< XFastAttributeList > & _xAttrList ,const Reference< XPropertySet >& _xControl ,OXMLControlProperty* _pContainer) : SvXMLImportContext( rImport ) ,m_xControl(_xControl) ,m_pContainer(_pContainer) ,m_bIsList(false) { m_aPropType = cppu::UnoType::get(); OSL_ENSURE(m_xControl.is(),"Control is NULL!"); for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList )) { OUString sValue = aIter.toString(); switch( aIter.getToken() ) { case XML_ELEMENT(FORM, XML_LIST_PROPERTY): m_bIsList = sValue == "true"; break; case XML_ELEMENT(OOO, XML_VALUE_TYPE): { // needs to be translated into a css::uno::Type static std::map< OUString, css::uno::Type > const s_aTypeNameMap { { GetXMLToken( XML_BOOLEAN) , cppu::UnoType::get() }, // Not a copy paste error, see comment xmloff/source/forms/propertyimport.cxx lines 244-248 { GetXMLToken( XML_FLOAT) , cppu::UnoType::get() }, { GetXMLToken( XML_DOUBLE) , cppu::UnoType::get() }, { GetXMLToken( XML_STRING) , cppu::UnoType::get() }, { GetXMLToken( XML_INT) , cppu::UnoType::get() }, { GetXMLToken( XML_SHORT) , cppu::UnoType::get() }, { GetXMLToken( XML_DATE) , cppu::UnoType::get() }, { GetXMLToken( XML_TIME) , cppu::UnoType::get() }, { GetXMLToken( XML_VOID) , cppu::UnoType::get() }, }; const std::map< OUString, css::uno::Type >::const_iterator aTypePos = s_aTypeNameMap.find(sValue); OSL_ENSURE(s_aTypeNameMap.end() != aTypePos, "OXMLControlProperty::OXMLControlProperty: invalid type!"); if (s_aTypeNameMap.end() != aTypePos) m_aPropType = aTypePos->second; } break; case XML_ELEMENT(FORM, XML_PROPERTY_NAME): m_aSetting.Name = sValue; break; default: SAL_WARN("reportdesign", "unknown attribute " << SvXMLImport::getPrefixAndNameFromToken(aIter.getToken()) << " = " << sValue); break; } } } OXMLControlProperty::~OXMLControlProperty() { } css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLControlProperty::createFastChildContext( sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) { css::uno::Reference< css::xml::sax::XFastContextHandler > xContext; ORptFilter& rImport = GetOwnImport(); switch( nElement ) { case XML_ELEMENT(FORM, XML_LIST_PROPERTY): rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP ); xContext = new OXMLControlProperty( rImport,xAttrList,m_xControl); break; case XML_ELEMENT(OOO, XML_VALUE): rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP ); xContext = new OXMLControlProperty( rImport,xAttrList,m_xControl,this ); break; default: break; } return xContext; } void OXMLControlProperty::endFastElement(sal_Int32 ) { if ( m_pContainer ) m_pContainer->addValue(m_aCharBuffer.makeStringAndClear()); if ( !(!m_aSetting.Name.isEmpty() && m_xControl.is()) ) return; if ( m_bIsList && !m_aSequence.hasElements() ) m_aSetting.Value <<= m_aSequence; try { m_xControl->setPropertyValue(m_aSetting.Name,m_aSetting.Value); } catch(const Exception&) { OSL_FAIL("Unknown property found!"); } } void OXMLControlProperty::characters( const OUString& rChars ) { m_aCharBuffer.append(rChars); } void OXMLControlProperty::addValue(const OUString& _sValue) { Any aValue; if( TypeClass_VOID != m_aPropType.getTypeClass() ) aValue = convertString(m_aPropType, _sValue); if ( !m_bIsList ) m_aSetting.Value = aValue; else { sal_Int32 nPos = m_aSequence.getLength(); m_aSequence.realloc(nPos+1); m_aSequence[nPos] = aValue; } } ORptFilter& OXMLControlProperty::GetOwnImport() { return static_cast(GetImport()); } Any OXMLControlProperty::convertString(const css::uno::Type& _rExpectedType, const OUString& _rReadCharacters) { Any aReturn; switch (_rExpectedType.getTypeClass()) { case TypeClass_BOOLEAN: // sal_Bool { bool bValue(false); bool bSuccess = ::sax::Converter::convertBool(bValue, _rReadCharacters); OSL_ENSURE(bSuccess, OStringBuffer("OXMLControlProperty::convertString: could not convert \""). append(OUStringToOString(_rReadCharacters, RTL_TEXTENCODING_ASCII_US)). append("\" into a boolean!").getStr()); aReturn <<= bValue; } break; case TypeClass_SHORT: // sal_Int16 case TypeClass_LONG: // sal_Int32 { // it's a real int32/16 property sal_Int32 nValue(0); bool bSuccess = ::sax::Converter::convertNumber(nValue, _rReadCharacters); OSL_ENSURE(bSuccess, OStringBuffer("OXMLControlProperty::convertString: could not convert \""). append(OUStringToOString(_rReadCharacters, RTL_TEXTENCODING_ASCII_US)). append("\" into an integer!").getStr()); if (TypeClass_SHORT == _rExpectedType.getTypeClass()) aReturn <<= static_cast(nValue); else aReturn <<= nValue; break; } case TypeClass_HYPER: { OSL_FAIL("OXMLControlProperty::convertString: 64-bit integers not implemented yet!"); } break; case TypeClass_DOUBLE: { double nValue = 0.0; bool bSuccess = ::sax::Converter::convertDouble(nValue, _rReadCharacters); OSL_ENSURE(bSuccess, OStringBuffer("OXMLControlProperty::convertString: could not convert \""). append(OUStringToOString(_rReadCharacters, RTL_TEXTENCODING_ASCII_US)). append("\" into a double!").getStr()); aReturn <<= nValue; } break; case TypeClass_STRING: aReturn <<= _rReadCharacters; break; case TypeClass_STRUCT: { // recognized structs: static css::uno::Type s_aDateType = ::cppu::UnoType::get(); static css::uno::Type s_aTimeType = ::cppu::UnoType::get(); static css::uno::Type s_aDateTimeType = ::cppu::UnoType::get(); sal_Int32 nType = 0; if ( _rExpectedType.equals(s_aDateType) ) nType = TYPE_DATE; else if ( _rExpectedType.equals(s_aTimeType) ) nType = TYPE_TIME; else if ( _rExpectedType.equals(s_aDateTimeType) ) nType = TYPE_DATETIME; if ( nType ) { // first extract the double double nValue = 0; bool bSuccess = ::sax::Converter::convertDouble(nValue, _rReadCharacters); OSL_ENSURE(bSuccess, OStringBuffer("OPropertyImport::convertString: could not convert \""). append(OUStringToOString(_rReadCharacters, RTL_TEXTENCODING_ASCII_US)). append("\" into a double!").getStr()); // then convert it into the target type switch (nType) { case TYPE_DATE: { OSL_ENSURE(std::modf(nValue, &o3tl::temporary(double())) == 0, "OPropertyImport::convertString: a Date value with a fractional part?"); aReturn <<= implGetDate(nValue); } break; case TYPE_TIME: { OSL_ENSURE((static_cast(nValue)) == 0, "OPropertyImport::convertString: a tools::Time value with more than a fractional part?"); aReturn <<= implGetTime(nValue); } break; case TYPE_DATETIME: { css::util::Time aTime = implGetTime(nValue); css::util::Date aDate = implGetDate(nValue); css::util::DateTime aDateTime; aDateTime.NanoSeconds = aTime.NanoSeconds; aDateTime.Seconds = aTime.Seconds; aDateTime.Minutes = aTime.Minutes; aDateTime.Hours = aTime.Hours; aDateTime.Day = aDate.Day; aDateTime.Month = aDate.Month; aDateTime.Year = aDate.Year; aReturn <<= aDateTime; } break; default: break; } } else OSL_FAIL("OPropertyImport::convertString: unsupported property type!"); } break; default: OSL_FAIL("OXMLControlProperty::convertString: invalid type class!"); } return aReturn; } css::util::Time OXMLControlProperty::implGetTime(double _nValue) { css::util::Time aTime; sal_uInt64 nIntValue = ::rtl::math::round(_nValue * 86400000000000.0); aTime.NanoSeconds = static_cast( nIntValue % 1000000000 ); nIntValue /= 1000000000; aTime.Seconds = static_cast( nIntValue % 60 ); nIntValue /= 60; aTime.Minutes = static_cast( nIntValue % 60 ); nIntValue /= 60; OSL_ENSURE(nIntValue < 24, "OPropertyImport::implGetTime: more than a day?"); aTime.Hours = static_cast< sal_uInt16 >( nIntValue ); return aTime; } css::util::Date OXMLControlProperty::implGetDate(double _nValue) { Date aToolsDate(static_cast(_nValue)); css::util::Date aDate; ::utl::typeConvert(aToolsDate, aDate); return aDate; } } // namespace rptxml /* vim:set shiftwidth=4 softtabstop=4 expandtab: */