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