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 <i18nlangtag/languagetag.hxx>
32 #include <comphelper/diagnose_ex.hxx>
39 using namespace ::com::sun::star
;
40 using namespace ::com::sun::star::uno
;
41 using namespace ::com::sun::star::beans
;
42 using namespace ::com::sun::star::xsd
;
43 using namespace ::com::sun::star::util
;
44 using namespace ::com::sun::star::lang
;
45 using namespace ::com::sun::star::xforms
;
47 namespace NumberFormat
= ::com::sun::star::util::NumberFormat
;
50 //= XSDValidationHelper
53 XSDValidationHelper::XSDValidationHelper( ::osl::Mutex
& _rMutex
, const Reference
< XPropertySet
>& _rxIntrospectee
, const Reference
< frame::XModel
>& _rxContextDocument
)
54 :EFormsHelper( _rMutex
, _rxIntrospectee
, _rxContextDocument
)
55 ,m_bInspectingFormattedField( false )
59 Reference
< XPropertySetInfo
> xPSI
;
60 Reference
< XServiceInfo
> xSI( _rxIntrospectee
, UNO_QUERY
);
61 if ( m_xControlModel
.is() )
62 xPSI
= m_xControlModel
->getPropertySetInfo();
64 && xPSI
->hasPropertyByName( PROPERTY_FORMATKEY
)
65 && xPSI
->hasPropertyByName( PROPERTY_FORMATSSUPPLIER
)
67 && xSI
->supportsService( SERVICE_COMPONENT_FORMATTEDFIELD
)
69 m_bInspectingFormattedField
= true;
71 catch( const Exception
& )
73 TOOLS_WARN_EXCEPTION("extensions.propctrlr",
74 "caught an exception while examining the introspectee!");
79 void XSDValidationHelper::getAvailableDataTypeNames( std::vector
< OUString
>& /* [out] */ _rNames
) const
85 Reference
< XDataTypeRepository
> xRepository
= getDataTypeRepository();
86 if ( xRepository
.is() )
88 const Sequence
<OUString
> aElements
= xRepository
->getElementNames();
90 _rNames
.resize( aElements
.getLength() );
91 std::copy( aElements
.begin(), aElements
.end(), _rNames
.begin() );
94 catch( const Exception
& )
96 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::getAvailableDataTypeNames" );
101 Reference
< XDataTypeRepository
> XSDValidationHelper::getDataTypeRepository() const
103 Reference
< XDataTypeRepository
> xRepository
;
105 Reference
< xforms::XModel
> xModel( getCurrentFormModel( ) );
107 xRepository
= xModel
->getDataTypeRepository();
113 Reference
< XDataTypeRepository
> XSDValidationHelper::getDataTypeRepository( const OUString
& _rModelName
) const
115 Reference
< XDataTypeRepository
> xRepository
;
117 Reference
< xforms::XModel
> xModel( getFormModelByName( _rModelName
) );
119 xRepository
= xModel
->getDataTypeRepository();
125 Reference
< XDataType
> XSDValidationHelper::getDataType( const OUString
& _rName
) const
127 Reference
< XDataType
> xDataType
;
129 if ( !_rName
.isEmpty() )
131 Reference
< XDataTypeRepository
> xRepository
= getDataTypeRepository();
132 if ( xRepository
.is() )
133 xDataType
= xRepository
->getDataType( _rName
);
139 OUString
XSDValidationHelper::getValidatingDataTypeName( ) const
141 OUString sDataTypeName
;
144 Reference
< XPropertySet
> xBinding( getCurrentBinding() );
145 // it's allowed here to not (yet) have a binding
148 OSL_VERIFY( xBinding
->getPropertyValue( PROPERTY_XSD_DATA_TYPE
) >>= sDataTypeName
);
151 catch( const Exception
& )
153 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::getValidatingDataTypeName" );
155 return sDataTypeName
;
159 ::rtl::Reference
< XSDDataType
> XSDValidationHelper::getDataTypeByName( const OUString
& _rName
) const
161 ::rtl::Reference
< XSDDataType
> pReturn
;
165 Reference
< XDataType
> xValidatedAgainst
;
167 if ( !_rName
.isEmpty() )
168 xValidatedAgainst
= getDataType( _rName
);
170 if ( xValidatedAgainst
.is() )
171 pReturn
= new XSDDataType( xValidatedAgainst
);
173 catch( const Exception
& )
175 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::getDataTypeByName" );
182 ::rtl::Reference
< XSDDataType
> XSDValidationHelper::getValidatingDataType( ) const
184 return getDataTypeByName( getValidatingDataTypeName() );
188 bool XSDValidationHelper::cloneDataType( const ::rtl::Reference
< XSDDataType
>& _pDataType
, const OUString
& _rNewName
) const
190 OSL_ENSURE( _pDataType
.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type!" );
191 if ( !_pDataType
.is() )
196 Reference
< XDataTypeRepository
> xRepository( getDataTypeRepository() );
197 OSL_ENSURE( xRepository
.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type repository!" );
198 if ( !xRepository
.is() )
201 Reference
< XDataType
> xDataType( _pDataType
->getUnoDataType() );
202 OSL_ENSURE( xDataType
.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type (II)!" );
203 if ( !xDataType
.is() )
206 xRepository
->cloneDataType( xDataType
->getName(), _rNewName
);
208 catch( const Exception
& )
210 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::cloneDataType" );
216 bool XSDValidationHelper::removeDataTypeFromRepository( const OUString
& _rName
) const
220 Reference
< XDataTypeRepository
> xRepository( getDataTypeRepository() );
221 OSL_ENSURE( xRepository
.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type repository!" );
222 if ( !xRepository
.is() )
225 if ( !xRepository
->hasByName( _rName
) )
227 OSL_FAIL( "XSDValidationHelper::removeDataTypeFromRepository: invalid repository and/or data type!" );
231 xRepository
->revokeDataType( _rName
);
233 catch( const Exception
& )
235 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::removeDataTypeFromRepository" );
242 void XSDValidationHelper::setValidatingDataTypeByName( const OUString
& _rName
) const
246 Reference
< XPropertySet
> xBinding( getCurrentBinding() );
247 OSL_ENSURE( xBinding
.is(), "XSDValidationHelper::setValidatingDataTypeByName: no active binding - how this?" );
251 // get the old data type - this is necessary for notifying property changes
252 OUString sOldDataTypeName
;
253 OSL_VERIFY( xBinding
->getPropertyValue( PROPERTY_XSD_DATA_TYPE
) >>= sOldDataTypeName
);
254 Reference
< XPropertySet
> xOldType
;
256 xOldType
= getDataType( sOldDataTypeName
);
257 } catch( const Exception
& ) { }
259 // set the new data type name
260 xBinding
->setPropertyValue( PROPERTY_XSD_DATA_TYPE
, Any( _rName
) );
262 // retrieve the new data type object
263 Reference
< XPropertySet
> xNewType
= getDataType( _rName
);
265 // fire any changes in the properties which result from this new type
266 std::set
< OUString
> aFilter
; aFilter
.insert( PROPERTY_NAME
);
267 firePropertyChanges( xOldType
, xNewType
, aFilter
);
269 // fire the change in the Data Type property
270 OUString sNewDataTypeName
;
271 OSL_VERIFY( xBinding
->getPropertyValue( PROPERTY_XSD_DATA_TYPE
) >>= sNewDataTypeName
);
272 firePropertyChange( PROPERTY_XSD_DATA_TYPE
, Any( sOldDataTypeName
), Any( sNewDataTypeName
) );
275 catch( const Exception
& )
277 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
282 void XSDValidationHelper::copyDataType( const OUString
& _rFromModel
, const OUString
& _rToModel
,
283 const OUString
& _rDataTypeName
) const
285 if ( _rFromModel
== _rToModel
)
286 // nothing to do (me thinks)
291 Reference
< XDataTypeRepository
> xFromRepository
, xToRepository
;
292 if ( !_rFromModel
.isEmpty() )
293 xFromRepository
= getDataTypeRepository( _rFromModel
);
294 if ( !_rToModel
.isEmpty() )
295 xToRepository
= getDataTypeRepository( _rToModel
);
297 if ( !xFromRepository
.is() || !xToRepository
.is() )
300 if ( !xFromRepository
->hasByName( _rDataTypeName
) || xToRepository
->hasByName( _rDataTypeName
) )
301 // not existent in the source, or already existent (by name) in the destination
304 // determine the built-in type belonging to the source type
305 ::rtl::Reference
< XSDDataType
> pSourceType
= new XSDDataType( xFromRepository
->getDataType( _rDataTypeName
) );
306 OUString sTargetBaseType
= getBasicTypeNameForClass( pSourceType
->classify(), xToRepository
);
308 // create the target type
309 Reference
< XDataType
> xTargetType
= xToRepository
->cloneDataType( sTargetBaseType
, _rDataTypeName
);
310 ::rtl::Reference
< XSDDataType
> pTargetType
= new XSDDataType( xTargetType
);
313 pTargetType
->copyFacetsFrom( pSourceType
);
315 catch( const Exception
& )
317 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::copyDataType" );
322 void XSDValidationHelper::findDefaultFormatForIntrospectee()
326 ::rtl::Reference
< XSDDataType
> xDataType
= getValidatingDataType();
327 if ( xDataType
.is() )
329 // find a NumberFormat type corresponding to the DataTypeClass
330 sal_Int16 nNumberFormatType
= NumberFormat::NUMBER
;
331 switch ( xDataType
->classify() )
333 case DataTypeClass::DATETIME
:
334 nNumberFormatType
= NumberFormat::DATETIME
;
336 case DataTypeClass::DATE
:
337 nNumberFormatType
= NumberFormat::DATE
;
339 case DataTypeClass::TIME
:
340 nNumberFormatType
= NumberFormat::TIME
;
342 case DataTypeClass::STRING
:
343 case DataTypeClass::anyURI
:
344 case DataTypeClass::QName
:
345 case DataTypeClass::NOTATION
:
346 nNumberFormatType
= NumberFormat::TEXT
;
350 // get the number formatter from the introspectee
351 Reference
< XNumberFormatsSupplier
> xSupplier
;
352 Reference
< XNumberFormatTypes
> xFormatTypes
;
353 OSL_VERIFY( m_xControlModel
->getPropertyValue( PROPERTY_FORMATSSUPPLIER
) >>= xSupplier
);
354 if ( xSupplier
.is() )
355 xFormatTypes
.set(xSupplier
->getNumberFormats(), css::uno::UNO_QUERY
);
356 OSL_ENSURE( xFormatTypes
.is(), "XSDValidationHelper::findDefaultFormatForIntrospectee: no number formats for the introspectee!" );
357 if ( !xFormatTypes
.is() )
360 // and the standard format for the given NumberFormat type
361 sal_Int32 nDesiredFormat
= xFormatTypes
->getStandardFormat( nNumberFormatType
, SvtSysLocale().GetLanguageTag().getLocale() );
363 // set this at the introspectee
364 m_xControlModel
->setPropertyValue( PROPERTY_FORMATKEY
, Any( nDesiredFormat
) );
367 catch( const Exception
& )
369 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::findDefaultFormatForIntrospectee" );
374 OUString
XSDValidationHelper::getBasicTypeNameForClass( sal_Int16 _nClass
) const
376 return getBasicTypeNameForClass( _nClass
, getDataTypeRepository() );
380 OUString
XSDValidationHelper::getBasicTypeNameForClass( sal_Int16 _nClass
, const Reference
< XDataTypeRepository
>& _rxRepository
)
383 OSL_ENSURE( _rxRepository
.is(), "XSDValidationHelper::getBasicTypeNameForClass: invalid repository!" );
384 if ( !_rxRepository
.is() )
389 Reference
< XDataType
> xDataType
= _rxRepository
->getBasicDataType( _nClass
);
390 OSL_ENSURE( xDataType
.is(), "XSDValidationHelper::getBasicTypeNameForClass: invalid data type returned!" );
391 if ( xDataType
.is() )
392 sReturn
= xDataType
->getName();
394 catch( const Exception
& )
396 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::getBasicTypeNameForClass" );
406 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */