1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "xsdvalidationhelper.hxx"
21 #include "xsddatatypes.hxx"
22 #include "formstrings.hxx"
24 #include <com/sun/star/lang/XServiceInfo.hpp>
25 #include <com/sun/star/xsd/DataTypeClass.hpp>
26 #include <com/sun/star/util/NumberFormat.hpp>
27 #include <com/sun/star/util/XNumberFormatTypes.hpp>
28 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
29 #include <com/sun/star/xforms/XDataTypeRepository.hpp>
30 #include <unotools/syslocale.hxx>
31 #include <tools/diagnose_ex.h>
38 using namespace ::com::sun::star
;
39 using namespace ::com::sun::star::uno
;
40 using namespace ::com::sun::star::beans
;
41 using namespace ::com::sun::star::xsd
;
42 using namespace ::com::sun::star::util
;
43 using namespace ::com::sun::star::lang
;
44 using namespace ::com::sun::star::xforms
;
46 namespace NumberFormat
= ::com::sun::star::util::NumberFormat
;
49 //= XSDValidationHelper
52 XSDValidationHelper::XSDValidationHelper( ::osl::Mutex
& _rMutex
, const Reference
< XPropertySet
>& _rxIntrospectee
, const Reference
< frame::XModel
>& _rxContextDocument
)
53 :EFormsHelper( _rMutex
, _rxIntrospectee
, _rxContextDocument
)
54 ,m_bInspectingFormattedField( false )
58 Reference
< XPropertySetInfo
> xPSI
;
59 Reference
< XServiceInfo
> xSI( _rxIntrospectee
, UNO_QUERY
);
60 if ( m_xControlModel
.is() )
61 xPSI
= m_xControlModel
->getPropertySetInfo();
63 && xPSI
->hasPropertyByName( PROPERTY_FORMATKEY
)
64 && xPSI
->hasPropertyByName( PROPERTY_FORMATSSUPPLIER
)
66 && xSI
->supportsService( SERVICE_COMPONENT_FORMATTEDFIELD
)
68 m_bInspectingFormattedField
= true;
70 catch( const Exception
& )
72 OSL_FAIL( "XSDValidationHelper::XSDValidationHelper: caught an exception while examining the introspectee!" );
77 void XSDValidationHelper::getAvailableDataTypeNames( ::std::vector
< OUString
>& /* [out] */ _rNames
) const
83 Reference
< XDataTypeRepository
> xRepository
= getDataTypeRepository();
84 Sequence
< OUString
> aElements
;
85 if ( xRepository
.is() )
86 aElements
= xRepository
->getElementNames();
88 _rNames
.resize( aElements
.getLength() );
89 ::std::copy( aElements
.getConstArray(), aElements
.getConstArray() + aElements
.getLength(), _rNames
.begin() );
91 catch( const Exception
& )
93 OSL_FAIL( "XSDValidationHelper::getAvailableDataTypeNames: caught an exception!" );
98 Reference
< XDataTypeRepository
> XSDValidationHelper::getDataTypeRepository() const
100 Reference
< XDataTypeRepository
> xRepository
;
102 Reference
< xforms::XModel
> xModel( getCurrentFormModel( ) );
104 xRepository
= xModel
->getDataTypeRepository();
110 Reference
< XDataTypeRepository
> XSDValidationHelper::getDataTypeRepository( const OUString
& _rModelName
) const
112 Reference
< XDataTypeRepository
> xRepository
;
114 Reference
< xforms::XModel
> xModel( getFormModelByName( _rModelName
) );
116 xRepository
= xModel
->getDataTypeRepository();
122 Reference
< XDataType
> XSDValidationHelper::getDataType( const OUString
& _rName
) const
124 Reference
< XDataType
> xDataType
;
126 if ( !_rName
.isEmpty() )
128 Reference
< XDataTypeRepository
> xRepository
= getDataTypeRepository();
129 if ( xRepository
.is() )
130 xDataType
= xRepository
->getDataType( _rName
);
136 OUString
XSDValidationHelper::getValidatingDataTypeName( ) const
138 OUString sDataTypeName
;
141 Reference
< XPropertySet
> xBinding( getCurrentBinding() );
142 // it's allowed here to not (yet) have a binding
145 OSL_VERIFY( xBinding
->getPropertyValue( PROPERTY_XSD_DATA_TYPE
) >>= sDataTypeName
);
148 catch( const Exception
& )
150 OSL_FAIL( "XSDValidationHelper::getValidatingDataTypeName: caught an exception!" );
152 return sDataTypeName
;
156 ::rtl::Reference
< XSDDataType
> XSDValidationHelper::getDataTypeByName( const OUString
& _rName
) const
158 ::rtl::Reference
< XSDDataType
> pReturn
;
162 Reference
< XDataType
> xValidatedAgainst
;
164 if ( !_rName
.isEmpty() )
165 xValidatedAgainst
= getDataType( _rName
);
167 if ( xValidatedAgainst
.is() )
168 pReturn
= new XSDDataType( xValidatedAgainst
);
170 catch( const Exception
& )
172 OSL_FAIL( "XSDValidationHelper::getDataTypeByName: caught an exception!" );
179 ::rtl::Reference
< XSDDataType
> XSDValidationHelper::getValidatingDataType( ) const
181 return getDataTypeByName( getValidatingDataTypeName() );
185 bool XSDValidationHelper::cloneDataType( const ::rtl::Reference
< XSDDataType
>& _pDataType
, const OUString
& _rNewName
) const
187 OSL_ENSURE( _pDataType
.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type!" );
188 if ( !_pDataType
.is() )
193 Reference
< XDataTypeRepository
> xRepository( getDataTypeRepository() );
194 OSL_ENSURE( xRepository
.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type repository!" );
195 if ( !xRepository
.is() )
198 Reference
< XDataType
> xDataType( _pDataType
->getUnoDataType() );
199 OSL_ENSURE( xDataType
.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type (II)!" );
200 if ( !xDataType
.is() )
203 xRepository
->cloneDataType( xDataType
->getName(), _rNewName
);
205 catch( const Exception
& )
207 OSL_FAIL( "XSDValidationHelper::cloneDataType: caught an exception!" );
213 bool XSDValidationHelper::removeDataTypeFromRepository( const OUString
& _rName
) const
217 Reference
< XDataTypeRepository
> xRepository( getDataTypeRepository() );
218 OSL_ENSURE( xRepository
.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type repository!" );
219 if ( !xRepository
.is() )
222 if ( !xRepository
->hasByName( _rName
) )
224 OSL_FAIL( "XSDValidationHelper::removeDataTypeFromRepository: invalid repository and/or data type!" );
228 xRepository
->revokeDataType( _rName
);
230 catch( const Exception
& )
232 OSL_FAIL( "XSDValidationHelper::removeDataTypeFromRepository: caught an exception!" );
239 void XSDValidationHelper::setValidatingDataTypeByName( const OUString
& _rName
) const
243 Reference
< XPropertySet
> xBinding( getCurrentBinding() );
244 OSL_ENSURE( xBinding
.is(), "XSDValidationHelper::setValidatingDataTypeByName: no active binding - how this?" );
248 // get the old data type - this is necessary for notifying property changes
249 OUString sOldDataTypeName
;
250 OSL_VERIFY( xBinding
->getPropertyValue( PROPERTY_XSD_DATA_TYPE
) >>= sOldDataTypeName
);
251 Reference
< XPropertySet
> xOldType
;
252 try { xOldType
.set(getDataType( sOldDataTypeName
), css::uno::UNO_QUERY
); } catch( const Exception
& ) { }
254 // set the new data type name
255 xBinding
->setPropertyValue( PROPERTY_XSD_DATA_TYPE
, makeAny( _rName
) );
257 // retrieve the new data type object
258 Reference
< XPropertySet
> xNewType( getDataType( _rName
), UNO_QUERY
);
260 // fire any changes in the properties which result from this new type
261 std::set
< OUString
> aFilter
; aFilter
.insert( static_cast<const OUString
&>(PROPERTY_NAME
) );
262 firePropertyChanges( xOldType
, xNewType
, aFilter
);
264 // fire the change in the Data Type property
265 OUString sNewDataTypeName
;
266 OSL_VERIFY( xBinding
->getPropertyValue( PROPERTY_XSD_DATA_TYPE
) >>= sNewDataTypeName
);
267 firePropertyChange( PROPERTY_XSD_DATA_TYPE
, makeAny( sOldDataTypeName
), makeAny( sNewDataTypeName
) );
270 catch( const Exception
& )
272 DBG_UNHANDLED_EXCEPTION();
277 void XSDValidationHelper::copyDataType( const OUString
& _rFromModel
, const OUString
& _rToModel
,
278 const OUString
& _rDataTypeName
) const
280 if ( _rFromModel
== _rToModel
)
281 // nothing to do (me thinks)
286 Reference
< XDataTypeRepository
> xFromRepository
, xToRepository
;
287 if ( !_rFromModel
.isEmpty() )
288 xFromRepository
= getDataTypeRepository( _rFromModel
);
289 if ( !_rToModel
.isEmpty() )
290 xToRepository
= getDataTypeRepository( _rToModel
);
292 if ( !xFromRepository
.is() || !xToRepository
.is() )
295 if ( !xFromRepository
->hasByName( _rDataTypeName
) || xToRepository
->hasByName( _rDataTypeName
) )
296 // not existent in the source, or already existent (by name) in the destination
299 // determine the built-in type belonging to the source type
300 ::rtl::Reference
< XSDDataType
> pSourceType
= new XSDDataType( xFromRepository
->getDataType( _rDataTypeName
) );
301 OUString sTargetBaseType
= getBasicTypeNameForClass( pSourceType
->classify(), xToRepository
);
303 // create the target type
304 Reference
< XDataType
> xTargetType
= xToRepository
->cloneDataType( sTargetBaseType
, _rDataTypeName
);
305 ::rtl::Reference
< XSDDataType
> pTargetType
= new XSDDataType( xTargetType
);
308 pTargetType
->copyFacetsFrom( pSourceType
);
310 catch( const Exception
& )
312 OSL_FAIL( "XSDValidationHelper::copyDataType: caught an exception!" );
317 void XSDValidationHelper::findDefaultFormatForIntrospectee()
321 ::rtl::Reference
< XSDDataType
> xDataType
= getValidatingDataType();
322 if ( xDataType
.is() )
324 // find a NumberFormat type corresponding to the DataTypeClass
325 sal_Int16 nNumberFormatType
= NumberFormat::NUMBER
;
326 switch ( xDataType
->classify() )
328 case DataTypeClass::DATETIME
:
329 nNumberFormatType
= NumberFormat::DATETIME
;
331 case DataTypeClass::DATE
:
332 nNumberFormatType
= NumberFormat::DATE
;
334 case DataTypeClass::TIME
:
335 nNumberFormatType
= NumberFormat::TIME
;
337 case DataTypeClass::STRING
:
338 case DataTypeClass::anyURI
:
339 case DataTypeClass::QName
:
340 case DataTypeClass::NOTATION
:
341 nNumberFormatType
= NumberFormat::TEXT
;
345 // get the number formatter from the introspectee
346 Reference
< XNumberFormatsSupplier
> xSupplier
;
347 Reference
< XNumberFormatTypes
> xFormatTypes
;
348 OSL_VERIFY( m_xControlModel
->getPropertyValue( PROPERTY_FORMATSSUPPLIER
) >>= xSupplier
);
349 if ( xSupplier
.is() )
350 xFormatTypes
.set(xSupplier
->getNumberFormats(), css::uno::UNO_QUERY
);
351 OSL_ENSURE( xFormatTypes
.is(), "XSDValidationHelper::findDefaultFormatForIntrospectee: no number formats for the introspectee!" );
352 if ( !xFormatTypes
.is() )
355 // and the standard format for the given NumberFormat type
356 sal_Int32 nDesiredFormat
= xFormatTypes
->getStandardFormat( nNumberFormatType
, SvtSysLocale().GetLanguageTag().getLocale() );
358 // set this at the introspectee
359 m_xControlModel
->setPropertyValue( PROPERTY_FORMATKEY
, makeAny( nDesiredFormat
) );
362 catch( const Exception
& )
364 OSL_FAIL( "XSDValidationHelper::findDefaultFormatForIntrospectee: caught an exception!" );
369 OUString
XSDValidationHelper::getBasicTypeNameForClass( sal_Int16 _nClass
) const
371 return getBasicTypeNameForClass( _nClass
, getDataTypeRepository() );
375 OUString
XSDValidationHelper::getBasicTypeNameForClass( sal_Int16 _nClass
, Reference
< XDataTypeRepository
> _rxRepository
)
378 OSL_ENSURE( _rxRepository
.is(), "XSDValidationHelper::getBasicTypeNameForClass: invalid repository!" );
379 if ( !_rxRepository
.is() )
384 Reference
< XDataType
> xDataType
= _rxRepository
->getBasicDataType( _nClass
);
385 OSL_ENSURE( xDataType
.is(), "XSDValidationHelper::getBasicTypeNameForClass: invalid data type returned!" );
386 if ( xDataType
.is() )
387 sReturn
= xDataType
->getName();
389 catch( const Exception
& )
391 OSL_FAIL( "XSDValidationHelper::getBasicTypeNameForClass: caught an exception!" );
401 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */