xref: /trunk/main/forms/source/xforms/datatypes.cxx (revision 24acc546)
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