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 <tools/diagnose_ex.h>
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 OSL_FAIL( "XSDValidationHelper::XSDValidationHelper: caught an exception while examining the introspectee!" );
78 void XSDValidationHelper::getAvailableDataTypeNames( std::vector
< OUString
>& /* [out] */ _rNames
) const
84 Reference
< XDataTypeRepository
> xRepository
= getDataTypeRepository();
85 Sequence
< OUString
> aElements
;
86 if ( xRepository
.is() )
87 aElements
= xRepository
->getElementNames();
89 _rNames
.resize( aElements
.getLength() );
90 std::copy( aElements
.begin(), aElements
.end(), _rNames
.begin() );
92 catch( const Exception
& )
94 OSL_FAIL( "XSDValidationHelper::getAvailableDataTypeNames: caught an exception!" );
99 Reference
< XDataTypeRepository
> XSDValidationHelper::getDataTypeRepository() const
101 Reference
< XDataTypeRepository
> xRepository
;
103 Reference
< xforms::XModel
> xModel( getCurrentFormModel( ) );
105 xRepository
= xModel
->getDataTypeRepository();
111 Reference
< XDataTypeRepository
> XSDValidationHelper::getDataTypeRepository( const OUString
& _rModelName
) const
113 Reference
< XDataTypeRepository
> xRepository
;
115 Reference
< xforms::XModel
> xModel( getFormModelByName( _rModelName
) );
117 xRepository
= xModel
->getDataTypeRepository();
123 Reference
< XDataType
> XSDValidationHelper::getDataType( const OUString
& _rName
) const
125 Reference
< XDataType
> xDataType
;
127 if ( !_rName
.isEmpty() )
129 Reference
< XDataTypeRepository
> xRepository
= getDataTypeRepository();
130 if ( xRepository
.is() )
131 xDataType
= xRepository
->getDataType( _rName
);
137 OUString
XSDValidationHelper::getValidatingDataTypeName( ) const
139 OUString sDataTypeName
;
142 Reference
< XPropertySet
> xBinding( getCurrentBinding() );
143 // it's allowed here to not (yet) have a binding
146 OSL_VERIFY( xBinding
->getPropertyValue( PROPERTY_XSD_DATA_TYPE
) >>= sDataTypeName
);
149 catch( const Exception
& )
151 OSL_FAIL( "XSDValidationHelper::getValidatingDataTypeName: caught an exception!" );
153 return sDataTypeName
;
157 ::rtl::Reference
< XSDDataType
> XSDValidationHelper::getDataTypeByName( const OUString
& _rName
) const
159 ::rtl::Reference
< XSDDataType
> pReturn
;
163 Reference
< XDataType
> xValidatedAgainst
;
165 if ( !_rName
.isEmpty() )
166 xValidatedAgainst
= getDataType( _rName
);
168 if ( xValidatedAgainst
.is() )
169 pReturn
= new XSDDataType( xValidatedAgainst
);
171 catch( const Exception
& )
173 OSL_FAIL( "XSDValidationHelper::getDataTypeByName: caught an exception!" );
180 ::rtl::Reference
< XSDDataType
> XSDValidationHelper::getValidatingDataType( ) const
182 return getDataTypeByName( getValidatingDataTypeName() );
186 bool XSDValidationHelper::cloneDataType( const ::rtl::Reference
< XSDDataType
>& _pDataType
, const OUString
& _rNewName
) const
188 OSL_ENSURE( _pDataType
.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type!" );
189 if ( !_pDataType
.is() )
194 Reference
< XDataTypeRepository
> xRepository( getDataTypeRepository() );
195 OSL_ENSURE( xRepository
.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type repository!" );
196 if ( !xRepository
.is() )
199 Reference
< XDataType
> xDataType( _pDataType
->getUnoDataType() );
200 OSL_ENSURE( xDataType
.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type (II)!" );
201 if ( !xDataType
.is() )
204 xRepository
->cloneDataType( xDataType
->getName(), _rNewName
);
206 catch( const Exception
& )
208 OSL_FAIL( "XSDValidationHelper::cloneDataType: caught an exception!" );
214 bool XSDValidationHelper::removeDataTypeFromRepository( const OUString
& _rName
) const
218 Reference
< XDataTypeRepository
> xRepository( getDataTypeRepository() );
219 OSL_ENSURE( xRepository
.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type repository!" );
220 if ( !xRepository
.is() )
223 if ( !xRepository
->hasByName( _rName
) )
225 OSL_FAIL( "XSDValidationHelper::removeDataTypeFromRepository: invalid repository and/or data type!" );
229 xRepository
->revokeDataType( _rName
);
231 catch( const Exception
& )
233 OSL_FAIL( "XSDValidationHelper::removeDataTypeFromRepository: caught an exception!" );
240 void XSDValidationHelper::setValidatingDataTypeByName( const OUString
& _rName
) const
244 Reference
< XPropertySet
> xBinding( getCurrentBinding() );
245 OSL_ENSURE( xBinding
.is(), "XSDValidationHelper::setValidatingDataTypeByName: no active binding - how this?" );
249 // get the old data type - this is necessary for notifying property changes
250 OUString sOldDataTypeName
;
251 OSL_VERIFY( xBinding
->getPropertyValue( PROPERTY_XSD_DATA_TYPE
) >>= sOldDataTypeName
);
252 Reference
< XPropertySet
> xOldType
;
253 try { xOldType
.set(getDataType( sOldDataTypeName
), css::uno::UNO_QUERY
); } catch( const Exception
& ) { }
255 // set the new data type name
256 xBinding
->setPropertyValue( PROPERTY_XSD_DATA_TYPE
, makeAny( _rName
) );
258 // retrieve the new data type object
259 Reference
< XPropertySet
> xNewType( getDataType( _rName
), UNO_QUERY
);
261 // fire any changes in the properties which result from this new type
262 std::set
< OUString
> aFilter
; aFilter
.insert( PROPERTY_NAME
);
263 firePropertyChanges( xOldType
, xNewType
, aFilter
);
265 // fire the change in the Data Type property
266 OUString sNewDataTypeName
;
267 OSL_VERIFY( xBinding
->getPropertyValue( PROPERTY_XSD_DATA_TYPE
) >>= sNewDataTypeName
);
268 firePropertyChange( PROPERTY_XSD_DATA_TYPE
, makeAny( sOldDataTypeName
), makeAny( sNewDataTypeName
) );
271 catch( const Exception
& )
273 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
278 void XSDValidationHelper::copyDataType( const OUString
& _rFromModel
, const OUString
& _rToModel
,
279 const OUString
& _rDataTypeName
) const
281 if ( _rFromModel
== _rToModel
)
282 // nothing to do (me thinks)
287 Reference
< XDataTypeRepository
> xFromRepository
, xToRepository
;
288 if ( !_rFromModel
.isEmpty() )
289 xFromRepository
= getDataTypeRepository( _rFromModel
);
290 if ( !_rToModel
.isEmpty() )
291 xToRepository
= getDataTypeRepository( _rToModel
);
293 if ( !xFromRepository
.is() || !xToRepository
.is() )
296 if ( !xFromRepository
->hasByName( _rDataTypeName
) || xToRepository
->hasByName( _rDataTypeName
) )
297 // not existent in the source, or already existent (by name) in the destination
300 // determine the built-in type belonging to the source type
301 ::rtl::Reference
< XSDDataType
> pSourceType
= new XSDDataType( xFromRepository
->getDataType( _rDataTypeName
) );
302 OUString sTargetBaseType
= getBasicTypeNameForClass( pSourceType
->classify(), xToRepository
);
304 // create the target type
305 Reference
< XDataType
> xTargetType
= xToRepository
->cloneDataType( sTargetBaseType
, _rDataTypeName
);
306 ::rtl::Reference
< XSDDataType
> pTargetType
= new XSDDataType( xTargetType
);
309 pTargetType
->copyFacetsFrom( pSourceType
);
311 catch( const Exception
& )
313 OSL_FAIL( "XSDValidationHelper::copyDataType: caught an exception!" );
318 void XSDValidationHelper::findDefaultFormatForIntrospectee()
322 ::rtl::Reference
< XSDDataType
> xDataType
= getValidatingDataType();
323 if ( xDataType
.is() )
325 // find a NumberFormat type corresponding to the DataTypeClass
326 sal_Int16 nNumberFormatType
= NumberFormat::NUMBER
;
327 switch ( xDataType
->classify() )
329 case DataTypeClass::DATETIME
:
330 nNumberFormatType
= NumberFormat::DATETIME
;
332 case DataTypeClass::DATE
:
333 nNumberFormatType
= NumberFormat::DATE
;
335 case DataTypeClass::TIME
:
336 nNumberFormatType
= NumberFormat::TIME
;
338 case DataTypeClass::STRING
:
339 case DataTypeClass::anyURI
:
340 case DataTypeClass::QName
:
341 case DataTypeClass::NOTATION
:
342 nNumberFormatType
= NumberFormat::TEXT
;
346 // get the number formatter from the introspectee
347 Reference
< XNumberFormatsSupplier
> xSupplier
;
348 Reference
< XNumberFormatTypes
> xFormatTypes
;
349 OSL_VERIFY( m_xControlModel
->getPropertyValue( PROPERTY_FORMATSSUPPLIER
) >>= xSupplier
);
350 if ( xSupplier
.is() )
351 xFormatTypes
.set(xSupplier
->getNumberFormats(), css::uno::UNO_QUERY
);
352 OSL_ENSURE( xFormatTypes
.is(), "XSDValidationHelper::findDefaultFormatForIntrospectee: no number formats for the introspectee!" );
353 if ( !xFormatTypes
.is() )
356 // and the standard format for the given NumberFormat type
357 sal_Int32 nDesiredFormat
= xFormatTypes
->getStandardFormat( nNumberFormatType
, SvtSysLocale().GetLanguageTag().getLocale() );
359 // set this at the introspectee
360 m_xControlModel
->setPropertyValue( PROPERTY_FORMATKEY
, makeAny( nDesiredFormat
) );
363 catch( const Exception
& )
365 OSL_FAIL( "XSDValidationHelper::findDefaultFormatForIntrospectee: caught an exception!" );
370 OUString
XSDValidationHelper::getBasicTypeNameForClass( sal_Int16 _nClass
) const
372 return getBasicTypeNameForClass( _nClass
, getDataTypeRepository() );
376 OUString
XSDValidationHelper::getBasicTypeNameForClass( sal_Int16 _nClass
, const Reference
< XDataTypeRepository
>& _rxRepository
)
379 OSL_ENSURE( _rxRepository
.is(), "XSDValidationHelper::getBasicTypeNameForClass: invalid repository!" );
380 if ( !_rxRepository
.is() )
385 Reference
< XDataType
> xDataType
= _rxRepository
->getBasicDataType( _nClass
);
386 OSL_ENSURE( xDataType
.is(), "XSDValidationHelper::getBasicTypeNameForClass: invalid data type returned!" );
387 if ( xDataType
.is() )
388 sReturn
= xDataType
->getName();
390 catch( const Exception
& )
392 OSL_FAIL( "XSDValidationHelper::getBasicTypeNameForClass: caught an exception!" );
402 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */