LCOV - code coverage report
Current view: top level - forms/source/xforms - datatypes.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 0 402 0.0 %
Date: 2014-11-03 Functions: 0 96 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "datatypes.hxx"
      21             : #include "resourcehelper.hxx"
      22             : #include "property.hrc"
      23             : #include "convert.hxx"
      24             : 
      25             : #include <com/sun/star/xsd/WhiteSpaceTreatment.hpp>
      26             : #include <tools/datetime.hxx>
      27             : #include <rtl/math.hxx>
      28             : 
      29             : 
      30             : namespace xforms
      31             : {
      32             : 
      33             : 
      34             :     using ::com::sun::star::uno::Reference;
      35             :     using ::com::sun::star::uno::RuntimeException;
      36             :     using ::com::sun::star::uno::Any;
      37             :     using ::com::sun::star::uno::makeAny;
      38             :     using ::com::sun::star::uno::Type;
      39             :     using ::com::sun::star::uno::Sequence;
      40             :     using ::com::sun::star::uno::Exception;
      41             :     using ::com::sun::star::util::VetoException;
      42             :     using ::com::sun::star::util::Date;
      43             :     using ::com::sun::star::util::Time;
      44             :     using ::com::sun::star::util::DateTime;
      45             :     using ::com::sun::star::lang::IllegalArgumentException;
      46             :     using ::com::sun::star::lang::WrappedTargetException;
      47             :     using ::com::sun::star::beans::UnknownPropertyException;
      48             :     using ::com::sun::star::beans::PropertyVetoException;
      49             :     using ::com::sun::star::beans::XPropertyChangeListener;
      50             :     using ::com::sun::star::beans::XVetoableChangeListener;
      51             : 
      52             :     using ::com::sun::star::beans::PropertyAttribute::BOUND;
      53             :     using ::com::sun::star::beans::PropertyAttribute::READONLY;
      54             : 
      55             :     using namespace ::com::sun::star::xsd;
      56             :     using namespace ::frm;
      57             :     U_NAMESPACE_USE
      58             : 
      59           0 :     OXSDDataType::OXSDDataType( const OUString& _rName, sal_Int16 _nTypeClass )
      60             :         :OXSDDataType_PBase( m_aBHelper )
      61             :         ,m_bIsBasic( true )
      62             :         ,m_nTypeClass( _nTypeClass )
      63             :         ,m_sName( _rName )
      64             :         ,m_nWST( WhiteSpaceTreatment::Preserve )
      65           0 :         ,m_bPatternMatcherDirty( true )
      66             :     {
      67           0 :     }
      68             : 
      69             : 
      70           0 :     OXSDDataType::~OXSDDataType()
      71             :     {
      72           0 :     }
      73             : 
      74             : 
      75           0 :     void OXSDDataType::registerProperties()
      76             :     {
      77           0 :         registerProperty( PROPERTY_NAME,            PROPERTY_ID_NAME,           BOUND, &m_sName,    ::getCppuType( &m_sName ) );
      78           0 :         registerProperty( PROPERTY_XSD_WHITESPACE,  PROPERTY_ID_XSD_WHITESPACE, BOUND, &m_nWST,     ::getCppuType( &m_nWST ) );
      79           0 :         registerProperty( PROPERTY_XSD_PATTERN,     PROPERTY_ID_XSD_PATTERN,    BOUND, &m_sPattern, ::getCppuType( &m_sPattern ) );
      80             : 
      81           0 :         registerProperty( PROPERTY_XSD_IS_BASIC,    PROPERTY_ID_XSD_IS_BASIC,   READONLY, &m_bIsBasic,      ::getCppuType( &m_bIsBasic ) );
      82           0 :         registerProperty( PROPERTY_XSD_TYPE_CLASS,  PROPERTY_ID_XSD_TYPE_CLASS, READONLY, &m_nTypeClass,    ::getCppuType( &m_nTypeClass ) );
      83           0 :     }
      84             : 
      85             : 
      86           0 :     void OXSDDataType::initializeClone( const OXSDDataType& _rCloneSource )
      87             :     {
      88           0 :         m_bIsBasic   = false;
      89           0 :         m_nTypeClass = _rCloneSource.m_nTypeClass;
      90           0 :         m_sPattern   = _rCloneSource.m_sPattern;
      91           0 :         m_nWST       = _rCloneSource.m_nWST;
      92           0 :     }
      93             : 
      94             : 
      95           0 :     OXSDDataType* OXSDDataType::clone( const OUString& _rNewName ) const
      96             :     {
      97           0 :         OXSDDataType* pClone = createClone( _rNewName );
      98           0 :         pClone->initializeClone( *this );
      99           0 :         return pClone;
     100             :     }
     101             : 
     102             : 
     103           0 :     IMPLEMENT_FORWARD_XINTERFACE2( OXSDDataType, OXSDDataType_Base, ::comphelper::OPropertyContainer )
     104             : 
     105             : 
     106           0 :     IMPLEMENT_FORWARD_XTYPEPROVIDER2( OXSDDataType, OXSDDataType_Base, ::comphelper::OPropertyContainer )
     107             : 
     108             : #define SET_PROPERTY( propertyid, value, member ) \
     109             :     setFastPropertyValue( PROPERTY_ID_##propertyid, makeAny( value ) ); \
     110             :     SAL_WARN_IF( member != value, "forms.misc", "OXSDDataType::setFoo: inconsistency!" );
     111             : 
     112             : 
     113           0 :     OUString SAL_CALL OXSDDataType::getName(  ) throw (RuntimeException, std::exception)
     114             :     {
     115           0 :         return m_sName;
     116             :     }
     117             : 
     118             : 
     119           0 :     void SAL_CALL OXSDDataType::setName( const OUString& aName ) throw (RuntimeException, VetoException, std::exception)
     120             :     {
     121             :         // TODO: check the name for conflicts in the repository
     122           0 :         SET_PROPERTY( NAME, aName, m_sName );
     123           0 :     }
     124             : 
     125             : 
     126           0 :     OUString SAL_CALL OXSDDataType::getPattern() throw (RuntimeException, std::exception)
     127             :     {
     128           0 :         return m_sPattern;
     129             :     }
     130             : 
     131             : 
     132           0 :     void SAL_CALL OXSDDataType::setPattern( const OUString& _pattern ) throw (RuntimeException, std::exception)
     133             :     {
     134           0 :         SET_PROPERTY( XSD_PATTERN, _pattern, m_sPattern );
     135           0 :     }
     136             : 
     137             : 
     138           0 :     sal_Int16 SAL_CALL OXSDDataType::getWhiteSpaceTreatment() throw (RuntimeException, std::exception)
     139             :     {
     140           0 :         return m_nWST;
     141             :     }
     142             : 
     143             : 
     144           0 :     void SAL_CALL OXSDDataType::setWhiteSpaceTreatment( sal_Int16 _whitespacetreatment ) throw (RuntimeException, IllegalArgumentException, std::exception)
     145             :     {
     146           0 :         SET_PROPERTY( XSD_WHITESPACE, _whitespacetreatment, m_nWST );
     147           0 :     }
     148             : 
     149             : 
     150           0 :     sal_Bool SAL_CALL OXSDDataType::getIsBasic() throw (RuntimeException, std::exception)
     151             :     {
     152           0 :         return m_bIsBasic;
     153             :     }
     154             : 
     155             : 
     156             : 
     157           0 :     sal_Int16 SAL_CALL OXSDDataType::getTypeClass() throw (RuntimeException, std::exception)
     158             :     {
     159           0 :         return m_nTypeClass;
     160             :     }
     161             : 
     162             : 
     163           0 :     sal_Bool OXSDDataType::validate( const OUString& sValue ) throw( RuntimeException, std::exception )
     164             :     {
     165           0 :         return ( _validate( sValue ) == 0 );
     166             :     }
     167             : 
     168             : 
     169           0 :   OUString OXSDDataType::explainInvalid( const OUString& sValue ) throw( RuntimeException, std::exception )
     170             :     {
     171             :         // get reason
     172           0 :         sal_uInt16 nReason = _validate( sValue );
     173             : 
     174             :         // get resource and return localized string
     175             :         return ( nReason == 0 )
     176             :             ? OUString()
     177             :             : getResource( nReason, sValue,
     178           0 :                                    _explainInvalid( nReason ) );
     179             :     }
     180             : 
     181             : 
     182           0 :     OUString OXSDDataType::_explainInvalid( sal_uInt16 nReason )
     183             :     {
     184           0 :         if ( RID_STR_XFORMS_PATTERN_DOESNT_MATCH == nReason )
     185             :         {
     186             :             OSL_ENSURE( !m_sPattern.isEmpty(), "OXSDDataType::_explainInvalid: how can this error occur without a regular expression?" );
     187           0 :             return m_sPattern;
     188             :         }
     189           0 :         return OUString();
     190             :     }
     191             : 
     192             : 
     193             :     namespace
     194             :     {
     195           0 :         static void lcl_initializePatternMatcher( ::std::unique_ptr< RegexMatcher >& _rpMatcher, const OUString& _rPattern )
     196             :         {
     197           0 :             UErrorCode nMatchStatus = U_ZERO_ERROR;
     198           0 :             UnicodeString aIcuPattern( reinterpret_cast<const UChar *>(_rPattern.getStr()), _rPattern.getLength() );    // UChar != sal_Unicode in MinGW
     199           0 :             _rpMatcher.reset( new RegexMatcher( aIcuPattern, 0, nMatchStatus ) );
     200           0 :             OSL_ENSURE( U_SUCCESS( nMatchStatus ), "lcl_initializePatternMatcher: invalid pattern property!" );
     201             :                 // if asserts, then something changed our pattern without going to convertFastPropertyValue/checkPropertySanity
     202           0 :         }
     203             : 
     204           0 :         static bool lcl_matchString( RegexMatcher& _rMatcher, const OUString& _rText )
     205             :         {
     206           0 :             UErrorCode nMatchStatus = U_ZERO_ERROR;
     207           0 :             UnicodeString aInput( reinterpret_cast<const UChar *>(_rText.getStr()), _rText.getLength() );   // UChar != sal_Unicode in MinGW
     208           0 :             _rMatcher.reset( aInput );
     209           0 :             if ( _rMatcher.matches( nMatchStatus ) )
     210             :             {
     211           0 :                 int32_t nStart = _rMatcher.start( nMatchStatus );
     212           0 :                 int32_t nEnd   = _rMatcher.end  ( nMatchStatus );
     213           0 :                 if ( ( nStart == 0 ) && ( nEnd == _rText.getLength() ) )
     214           0 :                     return true;
     215             :             }
     216             : 
     217           0 :             return false;
     218             :         }
     219             :     }
     220             : 
     221             : 
     222           0 :     sal_uInt16 OXSDDataType::_validate( const OUString& _rValue )
     223             :     {
     224             :         // care for the regular expression
     225           0 :         if ( !m_sPattern.isEmpty() )
     226             :         {
     227             :             // ensure our pattern matcher is up to date
     228           0 :             if ( m_bPatternMatcherDirty )
     229             :             {
     230           0 :                 lcl_initializePatternMatcher( m_pPatternMatcher, m_sPattern );
     231           0 :                 m_bPatternMatcherDirty = false;
     232             :             }
     233             : 
     234             :             // let it match the string
     235           0 :             if ( !lcl_matchString( *m_pPatternMatcher.get(), _rValue ) )
     236           0 :                 return RID_STR_XFORMS_PATTERN_DOESNT_MATCH;
     237             :         }
     238             : 
     239           0 :         return 0;
     240             :     }
     241             : 
     242             : 
     243           0 :     sal_Bool OXSDDataType::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw(IllegalArgumentException)
     244             :     {
     245             :         // let the base class do the conversion
     246           0 :         if ( !OXSDDataType_PBase::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ) )
     247           0 :             return sal_False;
     248             : 
     249             :         // sanity checks
     250           0 :         OUString sErrorMessage;
     251           0 :         if ( !checkPropertySanity( _nHandle, _rConvertedValue, sErrorMessage ) )
     252             :         {
     253           0 :             IllegalArgumentException aException;
     254           0 :             aException.Message = sErrorMessage;
     255           0 :             aException.Context = *this;
     256           0 :             throw IllegalArgumentException( aException );
     257             :         }
     258             : 
     259           0 :         return sal_True;
     260             :     }
     261             : 
     262             : 
     263           0 :     void SAL_CALL OXSDDataType::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception, std::exception)
     264             :     {
     265           0 :         OXSDDataType_PBase::setFastPropertyValue_NoBroadcast( _nHandle, _rValue );
     266           0 :         if ( _nHandle == PROPERTY_ID_XSD_PATTERN )
     267           0 :             m_bPatternMatcherDirty = true;
     268           0 :     }
     269             : 
     270             : 
     271           0 :     bool OXSDDataType::checkPropertySanity( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rNewValue, OUString& _rErrorMessage )
     272             :     {
     273           0 :         if ( _nHandle == PROPERTY_ID_XSD_PATTERN )
     274             :         {
     275           0 :             OUString sPattern;
     276           0 :             OSL_VERIFY( _rNewValue >>= sPattern );
     277             : 
     278           0 :             UnicodeString aIcuPattern( reinterpret_cast<const UChar *>(sPattern.getStr()), sPattern.getLength() );  // UChar != sal_Unicode in MinGW
     279           0 :             UErrorCode nMatchStatus = U_ZERO_ERROR;
     280           0 :             RegexMatcher aMatcher( aIcuPattern, 0, nMatchStatus );
     281           0 :             if ( U_FAILURE( nMatchStatus ) )
     282             :             {
     283           0 :                 _rErrorMessage = "This is no valid pattern.";
     284           0 :                 return false;
     285           0 :             }
     286             :         }
     287           0 :         return true;
     288             :     }
     289             : 
     290             : 
     291           0 :     void SAL_CALL OXSDDataType::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException, std::exception)
     292             :     {
     293           0 :         OXSDDataType_PBase::setPropertyValue( aPropertyName, aValue );
     294           0 :     }
     295             : 
     296             : 
     297           0 :     Any SAL_CALL OXSDDataType::getPropertyValue( const OUString& PropertyName ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception)
     298             :     {
     299           0 :         return OXSDDataType_PBase::getPropertyValue( PropertyName );
     300             :     }
     301             : 
     302             : 
     303           0 :     void SAL_CALL OXSDDataType::addPropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception)
     304             :     {
     305           0 :         OXSDDataType_PBase::addPropertyChangeListener( aPropertyName, xListener );
     306           0 :     }
     307             : 
     308             : 
     309           0 :     void SAL_CALL OXSDDataType::removePropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& aListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception)
     310             :     {
     311           0 :         OXSDDataType_PBase::removePropertyChangeListener( aPropertyName, aListener );
     312           0 :     }
     313             : 
     314             : 
     315           0 :     void SAL_CALL OXSDDataType::addVetoableChangeListener( const OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception)
     316             :     {
     317           0 :         OXSDDataType_PBase::addVetoableChangeListener( PropertyName, aListener );
     318           0 :     }
     319             : 
     320             : 
     321           0 :     void SAL_CALL OXSDDataType::removeVetoableChangeListener( const OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception)
     322             :     {
     323           0 :         OXSDDataType_PBase::removeVetoableChangeListener( PropertyName, aListener );
     324           0 :     }
     325             : 
     326           0 :     OValueLimitedType_Base::OValueLimitedType_Base( const OUString& _rName, sal_Int16 _nTypeClass )
     327             :         :OXSDDataType( _rName, _nTypeClass )
     328             :         ,m_fCachedMaxInclusive( 0 )
     329             :         ,m_fCachedMaxExclusive( 0 )
     330             :         ,m_fCachedMinInclusive( 0 )
     331           0 :         ,m_fCachedMinExclusive( 0 )
     332             :     {
     333           0 :     }
     334             : 
     335             : 
     336           0 :     void OValueLimitedType_Base::initializeClone( const OXSDDataType& _rCloneSource )
     337             :     {
     338           0 :         OXSDDataType::initializeClone( _rCloneSource );
     339           0 :         initializeTypedClone( static_cast< const OValueLimitedType_Base& >( _rCloneSource ) );
     340           0 :     }
     341             : 
     342             : 
     343           0 :     void OValueLimitedType_Base::initializeTypedClone( const OValueLimitedType_Base& _rCloneSource )
     344             :     {
     345           0 :         m_aMaxInclusive   = _rCloneSource.m_aMaxInclusive;
     346           0 :         m_aMaxExclusive   = _rCloneSource.m_aMaxExclusive;
     347           0 :         m_aMinInclusive   = _rCloneSource.m_aMinInclusive;
     348           0 :         m_aMinExclusive   = _rCloneSource.m_aMinExclusive;
     349           0 :         m_fCachedMaxInclusive   = _rCloneSource.m_fCachedMaxInclusive;
     350           0 :         m_fCachedMaxExclusive   = _rCloneSource.m_fCachedMaxExclusive;
     351           0 :         m_fCachedMinInclusive   = _rCloneSource.m_fCachedMinInclusive;
     352           0 :         m_fCachedMinExclusive   = _rCloneSource.m_fCachedMinExclusive;
     353           0 :     }
     354             : 
     355             : 
     356           0 :     void SAL_CALL OValueLimitedType_Base::setFastPropertyValue_NoBroadcast(
     357             :         sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) throw (::com::sun::star::uno::Exception, std::exception)
     358             :     {
     359           0 :         OXSDDataType::setFastPropertyValue_NoBroadcast( _nHandle, _rValue );
     360             : 
     361             :         // if one of our limit properties has been set, translate it into a double
     362             :         // value, for later efficient validation
     363           0 :         switch ( _nHandle )
     364             :         {
     365             :         case PROPERTY_ID_XSD_MAX_INCLUSIVE_INT:
     366             :         case PROPERTY_ID_XSD_MAX_INCLUSIVE_DOUBLE:
     367             :         case PROPERTY_ID_XSD_MAX_INCLUSIVE_DATE:
     368             :         case PROPERTY_ID_XSD_MAX_INCLUSIVE_TIME:
     369             :         case PROPERTY_ID_XSD_MAX_INCLUSIVE_DATE_TIME:
     370           0 :             if ( m_aMaxInclusive.hasValue() )
     371           0 :                 normalizeValue( m_aMaxInclusive, m_fCachedMaxInclusive );
     372             :             else
     373           0 :                 m_fCachedMaxInclusive = 0;
     374           0 :             break;
     375             :         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_INT:
     376             :         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DOUBLE:
     377             :         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DATE:
     378             :         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_TIME:
     379             :         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DATE_TIME:
     380           0 :             if ( m_aMaxExclusive.hasValue() )
     381           0 :                 normalizeValue( m_aMaxExclusive, m_fCachedMaxExclusive );
     382             :             else
     383           0 :                 m_fCachedMaxExclusive = 0;
     384           0 :             break;
     385             :         case PROPERTY_ID_XSD_MIN_INCLUSIVE_INT:
     386             :         case PROPERTY_ID_XSD_MIN_INCLUSIVE_DOUBLE:
     387             :         case PROPERTY_ID_XSD_MIN_INCLUSIVE_DATE:
     388             :         case PROPERTY_ID_XSD_MIN_INCLUSIVE_TIME:
     389             :         case PROPERTY_ID_XSD_MIN_INCLUSIVE_DATE_TIME:
     390           0 :             if ( m_aMinInclusive.hasValue() )
     391           0 :                 normalizeValue( m_aMinInclusive, m_fCachedMinInclusive );
     392             :             else
     393           0 :                 m_fCachedMinInclusive = 0;
     394           0 :             break;
     395             :         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_INT:
     396             :         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DOUBLE:
     397             :         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DATE:
     398             :         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_TIME:
     399             :         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DATE_TIME:
     400           0 :             if ( m_aMinExclusive.hasValue() )
     401           0 :                 normalizeValue( m_aMinExclusive, m_fCachedMinExclusive );
     402             :             else
     403           0 :                 m_fCachedMinExclusive = 0;
     404           0 :             break;
     405             :         }
     406           0 :     }
     407             : 
     408             : 
     409           0 :     bool OValueLimitedType_Base::_getValue( const OUString& rValue, double& fValue )
     410             :     {
     411             :         // convert to double
     412             :         rtl_math_ConversionStatus eStatus;
     413             :         sal_Int32 nEnd;
     414             :         double f = ::rtl::math::stringToDouble(
     415           0 :             rValue, '.', sal_Unicode(0), &eStatus, &nEnd );
     416             : 
     417             :         // error checking...
     418           0 :         bool bReturn = false;
     419           0 :         if( eStatus == rtl_math_ConversionStatus_Ok
     420           0 :             && nEnd == rValue.getLength() )
     421             :         {
     422           0 :             bReturn = true;
     423           0 :             fValue = f;
     424             :         }
     425           0 :         return bReturn;
     426             :     }
     427             : 
     428             : 
     429           0 :     sal_uInt16 OValueLimitedType_Base::_validate( const OUString& rValue )
     430             :     {
     431           0 :         sal_uInt16 nReason = OXSDDataType::_validate( rValue );
     432           0 :         if( nReason == 0 )
     433             :         {
     434             : 
     435             :             // convert value and check format
     436             :             double f;
     437           0 :             if( ! _getValue( rValue, f ) )
     438           0 :                 nReason = RID_STR_XFORMS_VALUE_IS_NOT_A;
     439             : 
     440             :             // check range
     441           0 :             else if( ( m_aMaxInclusive.hasValue() ) && f > m_fCachedMaxInclusive )
     442           0 :                 nReason = RID_STR_XFORMS_VALUE_MAX_INCL;
     443           0 :             else if( ( m_aMaxExclusive.hasValue() ) && f >= m_fCachedMaxExclusive )
     444           0 :                 nReason = RID_STR_XFORMS_VALUE_MAX_EXCL;
     445           0 :             else if( ( m_aMinInclusive.hasValue() ) && f < m_fCachedMinInclusive )
     446           0 :                 nReason = RID_STR_XFORMS_VALUE_MIN_INCL;
     447           0 :             else if( ( m_aMinExclusive.hasValue() ) && f <= m_fCachedMinExclusive )
     448           0 :                 nReason = RID_STR_XFORMS_VALUE_MIN_EXCL;
     449             :         }
     450           0 :         return nReason;
     451             :     }
     452             : 
     453             : 
     454           0 :     OUString OValueLimitedType_Base::_explainInvalid( sal_uInt16 nReason )
     455             :     {
     456           0 :         OUStringBuffer sInfo;
     457           0 :         switch( nReason )
     458             :         {
     459             :         case 0:
     460             :             // nothing to do!
     461           0 :             break;
     462             : 
     463             :         case RID_STR_XFORMS_VALUE_IS_NOT_A:
     464           0 :             sInfo.append( getName() );
     465           0 :             break;
     466             : 
     467             :         case RID_STR_XFORMS_VALUE_MAX_INCL:
     468           0 :             sInfo.append( typedValueAsHumanReadableString( m_aMaxInclusive ) );
     469           0 :             break;
     470             : 
     471             :         case RID_STR_XFORMS_VALUE_MAX_EXCL:
     472           0 :             sInfo.append( typedValueAsHumanReadableString( m_aMaxExclusive ) );
     473           0 :             break;
     474             : 
     475             :         case RID_STR_XFORMS_VALUE_MIN_INCL:
     476           0 :             sInfo.append( typedValueAsHumanReadableString( m_aMinInclusive ) );
     477           0 :             break;
     478             : 
     479             :         case RID_STR_XFORMS_VALUE_MIN_EXCL:
     480           0 :             sInfo.append( typedValueAsHumanReadableString( m_aMinExclusive ) );
     481           0 :             break;
     482             : 
     483             :         default:
     484             :             OSL_FAIL( "OValueLimitedType::_explainInvalid: unknown reason!" );
     485           0 :             break;
     486             :         }
     487             : 
     488           0 :         return sInfo.makeStringAndClear();
     489             :     }
     490             : 
     491           0 :     OStringType::OStringType( const OUString& _rName, sal_Int16 _nTypeClass )
     492           0 :         :OStringType_Base( _rName, _nTypeClass )
     493             :     {
     494           0 :     }
     495             : 
     496             : 
     497           0 :     void OStringType::registerProperties()
     498             :     {
     499           0 :         OStringType_Base::registerProperties();
     500             : 
     501           0 :         REGISTER_VOID_PROP( XSD_LENGTH,     m_aLength,    sal_Int32 );
     502           0 :         REGISTER_VOID_PROP( XSD_MIN_LENGTH, m_aMinLength, sal_Int32 );
     503           0 :         REGISTER_VOID_PROP( XSD_MAX_LENGTH, m_aMaxLength, sal_Int32 );
     504           0 :     }
     505             : 
     506             : 
     507           0 :     IMPLEMENT_DEFAULT_TYPED_CLONING( OStringType, OStringType_Base )
     508             : 
     509             : 
     510           0 :     void OStringType::initializeTypedClone( const OStringType& _rCloneSource )
     511             :     {
     512           0 :         m_aLength       = _rCloneSource.m_aLength;
     513           0 :         m_aMinLength    = _rCloneSource.m_aMinLength;
     514           0 :         m_aMaxLength    = _rCloneSource.m_aMaxLength;
     515           0 :     }
     516             : 
     517             : 
     518           0 :     bool OStringType::checkPropertySanity( sal_Int32 _nHandle, const Any& _rNewValue, OUString& _rErrorMessage )
     519             :     {
     520             :         // let the base class do the conversion
     521           0 :         if ( !OStringType_Base::checkPropertySanity( _nHandle, _rNewValue, _rErrorMessage ) )
     522           0 :             return false;
     523             : 
     524           0 :         _rErrorMessage = OUString();
     525           0 :         switch ( _nHandle )
     526             :         {
     527             :             case PROPERTY_ID_XSD_LENGTH:
     528             :             case PROPERTY_ID_XSD_MIN_LENGTH:
     529             :             case PROPERTY_ID_XSD_MAX_LENGTH:
     530             :             {
     531           0 :                 sal_Int32 nValue( 0 );
     532           0 :                 OSL_VERIFY( _rNewValue >>= nValue );
     533           0 :                 if ( nValue <= 0 )
     534           0 :                     _rErrorMessage = "Length limits must denote positive integer values.";
     535             :                         // TODO/eforms: localize the error message
     536             :             }
     537           0 :             break;
     538             :         }
     539             : 
     540           0 :         return _rErrorMessage.isEmpty();
     541             :     }
     542             : 
     543             : 
     544           0 :     sal_uInt16 OStringType::_validate( const OUString& rValue )
     545             :     {
     546             :         // check regexp, whitespace etc. in parent class
     547           0 :         sal_uInt16 nReason = OStringType_Base::_validate( rValue );
     548             : 
     549           0 :         if( nReason == 0 )
     550             :         {
     551             :             // check string constraints
     552           0 :             sal_Int32 nLength = rValue.getLength();
     553           0 :             sal_Int32 nLimit = 0;
     554           0 :             if ( m_aLength >>= nLimit )
     555             :             {
     556           0 :                 if ( nLimit != nLength )
     557           0 :                     nReason = RID_STR_XFORMS_VALUE_LENGTH;
     558             :             }
     559             :             else
     560             :             {
     561           0 :                 if ( ( m_aMaxLength >>= nLimit ) && ( nLength > nLimit ) )
     562           0 :                     nReason = RID_STR_XFORMS_VALUE_MAX_LENGTH;
     563           0 :                 else if ( ( m_aMinLength >>= nLimit ) && ( nLength < nLimit ) )
     564           0 :                     nReason = RID_STR_XFORMS_VALUE_MIN_LENGTH;
     565             :             }
     566             :         }
     567           0 :         return nReason;
     568             :     }
     569             : 
     570             : 
     571           0 :     OUString OStringType::_explainInvalid( sal_uInt16 nReason )
     572             :     {
     573           0 :         sal_Int32 nValue = 0;
     574           0 :         OUStringBuffer sInfo;
     575           0 :         switch( nReason )
     576             :         {
     577             :         case 0:
     578             :             // nothing to do!
     579           0 :             break;
     580             : 
     581             :         case RID_STR_XFORMS_VALUE_LENGTH:
     582           0 :             if( m_aLength >>= nValue )
     583           0 :                 sInfo.append( nValue );
     584           0 :             break;
     585             : 
     586             :         case RID_STR_XFORMS_VALUE_MAX_LENGTH:
     587           0 :             if( m_aMaxLength >>= nValue )
     588           0 :                 sInfo.append( nValue );
     589           0 :             break;
     590             : 
     591             :         case RID_STR_XFORMS_VALUE_MIN_LENGTH:
     592           0 :             if( m_aMinLength >>= nValue )
     593           0 :                 sInfo.append( nValue );
     594           0 :             break;
     595             : 
     596             :         default:
     597           0 :             sInfo.append( OStringType_Base::_explainInvalid( nReason ) );
     598           0 :             break;
     599             :         }
     600           0 :         return sInfo.makeStringAndClear();
     601             :     }
     602             : 
     603           0 :     OBooleanType::OBooleanType( const OUString& _rName )
     604           0 :         :OBooleanType_Base( _rName, DataTypeClass::BOOLEAN )
     605             :     {
     606           0 :     }
     607             : 
     608             : 
     609           0 :     IMPLEMENT_DEFAULT_CLONING( OBooleanType, OBooleanType_Base )
     610             : 
     611             : 
     612           0 :     void OBooleanType::initializeTypedClone( const OBooleanType& /*_rCloneSource*/ )
     613             :     {
     614           0 :     }
     615             : 
     616             : 
     617           0 :     sal_uInt16 OBooleanType::_validate( const OUString& sValue )
     618             :     {
     619           0 :         sal_uInt16 nInvalidityReason = OBooleanType_Base::_validate( sValue );
     620           0 :         if ( nInvalidityReason )
     621           0 :             return nInvalidityReason;
     622             : 
     623           0 :         bool bValid = sValue == "0" || sValue == "1" || sValue == "true" || sValue == "false";
     624           0 :         return bValid ? 0 : RID_STR_XFORMS_INVALID_VALUE;
     625             :     }
     626             : 
     627             : 
     628           0 :     OUString OBooleanType::_explainInvalid( sal_uInt16 nReason )
     629             :     {
     630           0 :         return ( nReason == 0 ) ? OUString() : getName();
     631             :     }
     632             : 
     633           0 :     ODecimalType::ODecimalType( const OUString& _rName, sal_Int16 _nTypeClass )
     634           0 :         :ODecimalType_Base( _rName, _nTypeClass )
     635             :     {
     636           0 :     }
     637             : 
     638             : 
     639           0 :     IMPLEMENT_DEFAULT_TYPED_CLONING( ODecimalType, ODecimalType_Base )
     640             : 
     641             : 
     642           0 :     void ODecimalType::initializeTypedClone( const ODecimalType& _rCloneSource )
     643             :     {
     644           0 :         m_aTotalDigits    = _rCloneSource.m_aTotalDigits;
     645           0 :         m_aFractionDigits = _rCloneSource.m_aFractionDigits;
     646           0 :     }
     647             : 
     648             : 
     649           0 :     void ODecimalType::registerProperties()
     650             :     {
     651           0 :         ODecimalType_Base::registerProperties();
     652             : 
     653           0 :         REGISTER_VOID_PROP( XSD_TOTAL_DIGITS,    m_aTotalDigits,    sal_Int32 );
     654           0 :         REGISTER_VOID_PROP( XSD_FRACTION_DIGITS, m_aFractionDigits, sal_Int32 );
     655           0 :     }
     656             : 
     657             : 
     658             : 
     659             :     // validate decimals and return code for which facets failed
     660             :     // to be used by: ODecimalType::validate and ODecimalType::explainInvalid
     661           0 :     sal_uInt16 ODecimalType::_validate( const OUString& rValue )
     662             :     {
     663           0 :         sal_Int16 nReason = ODecimalType_Base::_validate( rValue );
     664             : 
     665             :         // check digits (if no other cause is available so far)
     666           0 :         if( nReason == 0 )
     667             :         {
     668           0 :             sal_Int32 nLength = rValue.getLength();
     669           0 :             sal_Int32 n = 0;
     670           0 :             sal_Int32 nTotalDigits = 0;
     671           0 :             sal_Int32 nFractionDigits = 0;
     672           0 :             const sal_Unicode* pValue = rValue.getStr();
     673           0 :             for( ; n < nLength && pValue[n] != '.'; n++ )
     674           0 :                 if( pValue[n] >= '0'
     675           0 :                     && pValue[n] <= '9')
     676           0 :                     nTotalDigits++;
     677           0 :             for( ; n < nLength; n++ )
     678           0 :                 if( pValue[n] >= '0'
     679           0 :                     && pValue[n] <= '9')
     680           0 :                     nFractionDigits++;
     681           0 :             nTotalDigits += nFractionDigits;
     682             : 
     683           0 :             sal_Int32 nValue = 0;
     684           0 :             if( ( m_aTotalDigits >>= nValue ) &&  nTotalDigits > nValue )
     685           0 :                 nReason = RID_STR_XFORMS_VALUE_TOTAL_DIGITS;
     686           0 :             else if( ( m_aFractionDigits >>= nValue ) &&
     687           0 :                      ( nFractionDigits > nValue ) )
     688           0 :                 nReason = RID_STR_XFORMS_VALUE_FRACTION_DIGITS;
     689             :         }
     690             : 
     691           0 :         return nReason;
     692             :     }
     693             : 
     694             : 
     695           0 :     OUString ODecimalType::_explainInvalid( sal_uInt16 nReason )
     696             :     {
     697           0 :         sal_Int32 nValue = 0;
     698           0 :         OUStringBuffer sInfo;
     699           0 :         switch( nReason )
     700             :         {
     701             :         case RID_STR_XFORMS_VALUE_TOTAL_DIGITS:
     702           0 :             if( m_aTotalDigits >>= nValue )
     703           0 :                 sInfo.append( nValue );
     704           0 :             break;
     705             : 
     706             :         case RID_STR_XFORMS_VALUE_FRACTION_DIGITS:
     707           0 :             if( m_aFractionDigits >>= nValue )
     708           0 :                 sInfo.append( nValue );
     709           0 :             break;
     710             : 
     711             :         default:
     712           0 :             sInfo.append( ODecimalType_Base::_explainInvalid( nReason ) );
     713           0 :             break;
     714             :         }
     715           0 :         return sInfo.makeStringAndClear();
     716             :     }
     717             : 
     718             : 
     719           0 :     OUString ODecimalType::typedValueAsHumanReadableString( const Any& _rValue ) const
     720             :     {
     721           0 :         double fValue( 0 );
     722           0 :         normalizeValue( _rValue, fValue );
     723           0 :         return OUString::number( fValue );
     724             :     }
     725             : 
     726             : 
     727           0 :     void ODecimalType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const
     728             :     {
     729           0 :         OSL_VERIFY( _rValue >>= _rDoubleValue );
     730           0 :     }
     731             : 
     732             : 
     733             :     //=
     734             : 
     735             : #define DEFAULT_IMPLEMNENT_SUBTYPE( classname, typeclass )      \
     736             :     classname::classname( const OUString& _rName )       \
     737             :         :classname##_Base( _rName, DataTypeClass::typeclass )   \
     738             :     {                                                           \
     739             :     }                                                           \
     740             :                                                                 \
     741             :     IMPLEMENT_DEFAULT_CLONING( classname, classname##_Base )    \
     742             :                                                                 \
     743             :     void classname::initializeTypedClone( const classname& /*_rCloneSource*/ )  \
     744             :     {                                                           \
     745             :     }                                                           \
     746             : 
     747             : 
     748             : 
     749             :     //= ODateType
     750             : 
     751             : 
     752           0 :     DEFAULT_IMPLEMNENT_SUBTYPE( ODateType, DATE )
     753             : 
     754             : 
     755           0 :     sal_uInt16 ODateType::_validate( const OUString& _rValue )
     756             :     {
     757           0 :         return ODateType_Base::_validate( _rValue );
     758             :     }
     759             : 
     760             : 
     761           0 :     bool ODateType::_getValue( const OUString& value, double& fValue )
     762             :     {
     763           0 :         Any aTypeValue = Convert::get().toAny( value, getCppuType() );
     764             : 
     765           0 :         Date aValue;
     766           0 :         if ( !( aTypeValue >>= aValue ) )
     767           0 :             return false;
     768             : 
     769           0 :         ::Date aToolsDate( aValue.Day, aValue.Month, aValue.Year );
     770           0 :         fValue = aToolsDate.GetDate();
     771           0 :         return true;
     772             :     }
     773             : 
     774             : 
     775           0 :     OUString ODateType::typedValueAsHumanReadableString( const Any& _rValue ) const
     776             :     {
     777             :         OSL_PRECOND( _rValue.getValueType().equals( getCppuType() ), "ODateType::typedValueAsHumanReadableString: unexpected type" );
     778           0 :         return Convert::get().toXSD( _rValue );
     779             :     }
     780             : 
     781             : 
     782           0 :     void ODateType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const
     783             :     {
     784           0 :         Date aValue;
     785           0 :         OSL_VERIFY( _rValue >>= aValue );
     786           0 :         ::Date aToolsDate( aValue.Day, aValue.Month, aValue.Year );
     787           0 :         _rDoubleValue = aToolsDate.GetDate();
     788           0 :     }
     789             : 
     790             : 
     791             :     //= OTimeType
     792             : 
     793             : 
     794           0 :     DEFAULT_IMPLEMNENT_SUBTYPE( OTimeType, TIME )
     795             : 
     796             : 
     797           0 :     sal_uInt16 OTimeType::_validate( const OUString& _rValue )
     798             :     {
     799           0 :         return OTimeType_Base::_validate( _rValue );
     800             :     }
     801             : 
     802             : 
     803           0 :     bool OTimeType::_getValue( const OUString& value, double& fValue )
     804             :     {
     805           0 :         Any aTypedValue = Convert::get().toAny( value, getCppuType() );
     806             : 
     807           0 :         css::util::Time aValue;
     808           0 :         if ( !( aTypedValue >>= aValue ) )
     809           0 :             return false;
     810             : 
     811           0 :         ::tools::Time aToolsTime( aValue.Hours, aValue.Minutes, aValue.Seconds, aValue.NanoSeconds );
     812             :         // no loss/rounding; IEEE 754 double-precision floating-point
     813             :         // has a mantissa of 53 bits; we need at the very most 50 bits:
     814             :         // format of aToolsTime.GetTime() is (in decimal) hhmmssnnnnnnnnn
     815             :         // and 999999999999999 = 0x38D7EA4C67FFF
     816             :         // in reality I doubt we need (much) more than
     817             :         //     240000000000000 = 0x0DA475ABF0000
     818             :         // that is 48 bits
     819           0 :         fValue = aToolsTime.GetTime();
     820           0 :         return true;
     821             :     }
     822             : 
     823             : 
     824           0 :     OUString OTimeType::typedValueAsHumanReadableString( const Any& _rValue ) const
     825             :     {
     826             :         OSL_PRECOND( _rValue.getValueType().equals( getCppuType() ), "OTimeType::typedValueAsHumanReadableString: unexpected type" );
     827           0 :         return Convert::get().toXSD( _rValue );
     828             :     }
     829             : 
     830             : 
     831           0 :     void OTimeType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const
     832             :     {
     833           0 :         css::util::Time aValue;
     834           0 :         OSL_VERIFY( _rValue >>= aValue );
     835           0 :         ::tools::Time aToolsTime( aValue.Hours, aValue.Minutes, aValue.Seconds, aValue.NanoSeconds );
     836           0 :         _rDoubleValue = aToolsTime.GetTime();
     837           0 :     }
     838             : 
     839             : 
     840             :     //= ODateTimeType
     841             : 
     842             : 
     843           0 :     DEFAULT_IMPLEMNENT_SUBTYPE( ODateTimeType, DATETIME )
     844             : 
     845             : 
     846           0 :     sal_uInt16 ODateTimeType::_validate( const OUString& _rValue )
     847             :     {
     848           0 :         return ODateTimeType_Base::_validate( _rValue );
     849             :     }
     850             : 
     851             : 
     852             :     namespace
     853             :     {
     854           0 :         double lcl_normalizeDateTime( const DateTime& _rValue )
     855             :         {
     856             :             ::DateTime aToolsValue(
     857             :                 ::Date( _rValue.Day, _rValue.Month, _rValue.Year ),
     858             :                 ::tools::Time( _rValue.Hours, _rValue.Minutes, _rValue.Seconds, _rValue.NanoSeconds )
     859           0 :             );
     860             : 
     861           0 :             double fValue = 0;
     862             :             // days since 1.1.1900 (which is relatively arbitrary but fixed date)
     863           0 :             fValue += ::Date( aToolsValue ) - ::Date( 1, 1, 1900 );
     864             :             // time
     865           0 :             fValue += aToolsValue.GetTimeInDays();
     866           0 :             return fValue;
     867             :         }
     868             :     }
     869             : 
     870             : 
     871           0 :     bool ODateTimeType::_getValue( const OUString& value, double& fValue )
     872             :     {
     873           0 :         Any aTypedValue = Convert::get().toAny( value, getCppuType() );
     874             : 
     875           0 :         DateTime aValue;
     876           0 :         if ( !( aTypedValue >>= aValue ) )
     877           0 :             return false;
     878             : 
     879           0 :         fValue = lcl_normalizeDateTime( aValue );
     880           0 :         return true;
     881             :     }
     882             : 
     883             : 
     884           0 :     OUString ODateTimeType::typedValueAsHumanReadableString( const Any& _rValue ) const
     885             :     {
     886             :         OSL_PRECOND( _rValue.getValueType().equals( getCppuType() ), "OTimeType::typedValueAsHumanReadableString: unexpected type" );
     887           0 :         OUString sString = Convert::get().toXSD( _rValue );
     888             : 
     889             :         // ISO 8601 notation has a "T" to separate between date and time. Our only concession
     890             :         // to the "human readable" in the method name is to replace this T with a whitespace.
     891             :         OSL_ENSURE( sString.indexOf( 'T' ) != -1, "ODateTimeType::typedValueAsHumanReadableString: hmm - no ISO notation?" );
     892           0 :         return sString.replace( 'T', ' ' );
     893             :     }
     894             : 
     895             : 
     896           0 :     void ODateTimeType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const
     897             :     {
     898           0 :         DateTime aValue;
     899           0 :         OSL_VERIFY( _rValue >>= aValue );
     900           0 :         _rDoubleValue = lcl_normalizeDateTime( aValue );
     901           0 :     }
     902             : 
     903           0 :     OShortIntegerType::OShortIntegerType( const OUString& _rName, sal_Int16 _nTypeClass )
     904           0 :         :OShortIntegerType_Base( _rName, _nTypeClass )
     905             :     {
     906           0 :     }
     907             : 
     908             : 
     909           0 :     IMPLEMENT_DEFAULT_TYPED_CLONING( OShortIntegerType, OShortIntegerType_Base )
     910             : 
     911             : 
     912           0 :     void OShortIntegerType::initializeTypedClone( const OShortIntegerType& /*_rCloneSource*/ )
     913             :     {
     914           0 :     }
     915             : 
     916             : 
     917           0 :     bool OShortIntegerType::_getValue( const OUString& value, double& fValue )
     918             :     {
     919           0 :         fValue = (double)(sal_Int16)value.toInt32();
     920             :         // TODO/eforms
     921             :         // this does not care for values which do not fit into a sal_Int16, but simply
     922             :         // cuts them down. A better implementation here should probably return <FALSE/>
     923             :         // for those values.
     924             :         // Else, we may have a situation where the UI claims an input to be valid
     925             :         // (say "12345678"), while internally, and at submission time, this is cut to
     926             :         // some smaller value.
     927             : 
     928             :         // Additionally, this of course does not care for strings which are no numers ...
     929           0 :         return true;
     930             :     }
     931             : 
     932             : 
     933           0 :     OUString OShortIntegerType::typedValueAsHumanReadableString( const Any& _rValue ) const
     934             :     {
     935           0 :         sal_Int16 nValue( 0 );
     936           0 :         OSL_VERIFY( _rValue >>= nValue );
     937           0 :         return OUString::number( nValue );
     938             :     }
     939             : 
     940             : 
     941           0 :     void OShortIntegerType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const
     942             :     {
     943           0 :         sal_Int16 nValue( 0 );
     944           0 :         OSL_VERIFY( _rValue >>= nValue );
     945           0 :         _rDoubleValue = nValue;
     946           0 :     }
     947             : 
     948             : 
     949             : 
     950             : #define DATATYPES_INCLUDED_BY_MASTER_HEADER
     951             : #include "datatypes_impl.hxx"
     952             : #undef DATATYPES_INCLUDED_BY_MASTER_HEADER
     953             : 
     954             : 
     955             : } // namespace xforms
     956             : 
     957             : 
     958             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10