1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_extensions.hxx" 30 #include "xsdvalidationhelper.hxx" 31 #include "xsddatatypes.hxx" 32 #include "formstrings.hxx" 33 34 /** === begin UNO includes === **/ 35 #include <com/sun/star/lang/XServiceInfo.hpp> 36 #include <com/sun/star/xsd/DataTypeClass.hpp> 37 #include <com/sun/star/util/NumberFormat.hpp> 38 #include <com/sun/star/util/XNumberFormatTypes.hpp> 39 #include <com/sun/star/util/XNumberFormatsSupplier.hpp> 40 #include <com/sun/star/xforms/XDataTypeRepository.hpp> 41 /** === end UNO includes === **/ 42 #include <unotools/syslocale.hxx> 43 #include <tools/diagnose_ex.h> 44 45 //........................................................................ 46 namespace pcr 47 { 48 //........................................................................ 49 50 using namespace ::com::sun::star; 51 using namespace ::com::sun::star::uno; 52 using namespace ::com::sun::star::beans; 53 using namespace ::com::sun::star::xsd; 54 using namespace ::com::sun::star::util; 55 using namespace ::com::sun::star::lang; 56 using namespace ::com::sun::star::xforms; 57 58 namespace NumberFormat = ::com::sun::star::util::NumberFormat; 59 60 //==================================================================== 61 //= XSDValidationHelper 62 //==================================================================== 63 //-------------------------------------------------------------------- 64 XSDValidationHelper::XSDValidationHelper( ::osl::Mutex& _rMutex, const Reference< XPropertySet >& _rxIntrospectee, const Reference< frame::XModel >& _rxContextDocument ) 65 :EFormsHelper( _rMutex, _rxIntrospectee, _rxContextDocument ) 66 ,m_bInspectingFormattedField( false ) 67 { 68 try 69 { 70 Reference< XPropertySetInfo > xPSI; 71 Reference< XServiceInfo > xSI( _rxIntrospectee, UNO_QUERY ); 72 if ( m_xControlModel.is() ) 73 xPSI = m_xControlModel->getPropertySetInfo(); 74 if ( xPSI.is() 75 && xPSI->hasPropertyByName( PROPERTY_FORMATKEY ) 76 && xPSI->hasPropertyByName( PROPERTY_FORMATSSUPPLIER ) 77 && xSI.is() 78 && xSI->supportsService( SERVICE_COMPONENT_FORMATTEDFIELD ) 79 ) 80 m_bInspectingFormattedField = true; 81 } 82 catch( const Exception& ) 83 { 84 OSL_ENSURE( sal_False, "XSDValidationHelper::XSDValidationHelper: caught an exception while examining the introspectee!" ); 85 } 86 } 87 88 //-------------------------------------------------------------------- 89 void XSDValidationHelper::getAvailableDataTypeNames( ::std::vector< ::rtl::OUString >& /* [out] */ _rNames ) const SAL_THROW(()) 90 { 91 _rNames.resize( 0 ); 92 93 try 94 { 95 Reference< XDataTypeRepository > xRepository = getDataTypeRepository(); 96 Sequence< ::rtl::OUString > aElements; 97 if ( xRepository.is() ) 98 aElements = xRepository->getElementNames(); 99 100 _rNames.resize( aElements.getLength() ); 101 ::std::copy( aElements.getConstArray(), aElements.getConstArray() + aElements.getLength(), _rNames.begin() ); 102 } 103 catch( const Exception& ) 104 { 105 OSL_ENSURE( sal_False, "XSDValidationHelper::getAvailableDataTypeNames: caught an exception!" ); 106 } 107 } 108 109 //-------------------------------------------------------------------- 110 Reference< XDataTypeRepository > XSDValidationHelper::getDataTypeRepository() const SAL_THROW((Exception)) 111 { 112 Reference< XDataTypeRepository > xRepository; 113 114 Reference< xforms::XModel > xModel( getCurrentFormModel( ) ); 115 if ( xModel.is() ) 116 xRepository = xModel->getDataTypeRepository(); 117 118 return xRepository; 119 } 120 121 //-------------------------------------------------------------------- 122 Reference< XDataTypeRepository > XSDValidationHelper::getDataTypeRepository( const ::rtl::OUString& _rModelName ) const SAL_THROW((Exception)) 123 { 124 Reference< XDataTypeRepository > xRepository; 125 126 Reference< xforms::XModel > xModel( getFormModelByName( _rModelName ) ); 127 if ( xModel.is() ) 128 xRepository = xModel->getDataTypeRepository(); 129 130 return xRepository; 131 } 132 133 //-------------------------------------------------------------------- 134 Reference< XDataType > XSDValidationHelper::getDataType( const ::rtl::OUString& _rName ) const SAL_THROW((Exception)) 135 { 136 Reference< XDataType > xDataType; 137 138 if ( _rName.getLength() ) 139 { 140 Reference< XDataTypeRepository > xRepository = getDataTypeRepository(); 141 if ( xRepository.is() ) 142 xDataType = xRepository->getDataType( _rName ); 143 } 144 return xDataType; 145 } 146 147 //-------------------------------------------------------------------- 148 ::rtl::OUString XSDValidationHelper::getValidatingDataTypeName( ) const SAL_THROW(()) 149 { 150 ::rtl::OUString sDataTypeName; 151 try 152 { 153 Reference< XPropertySet > xBinding( getCurrentBinding() ); 154 // it's allowed here to not (yet) have a binding 155 if ( xBinding.is() ) 156 { 157 OSL_VERIFY( xBinding->getPropertyValue( PROPERTY_XSD_DATA_TYPE ) >>= sDataTypeName ); 158 } 159 } 160 catch( const Exception& ) 161 { 162 OSL_ENSURE( sal_False, "XSDValidationHelper::getValidatingDataTypeName: caught an exception!" ); 163 } 164 return sDataTypeName; 165 } 166 167 //-------------------------------------------------------------------- 168 ::rtl::Reference< XSDDataType > XSDValidationHelper::getDataTypeByName( const ::rtl::OUString& _rName ) const SAL_THROW(()) 169 { 170 ::rtl::Reference< XSDDataType > pReturn; 171 172 try 173 { 174 Reference< XDataType > xValidatedAgainst; 175 176 if ( _rName.getLength() ) 177 xValidatedAgainst = getDataType( _rName ); 178 179 if ( xValidatedAgainst.is() ) 180 pReturn = new XSDDataType( xValidatedAgainst ); 181 } 182 catch( const Exception& ) 183 { 184 OSL_ENSURE( sal_False, "XSDValidationHelper::getDataTypeByName: caught an exception!" ); 185 } 186 187 return pReturn; 188 } 189 190 //-------------------------------------------------------------------- 191 ::rtl::Reference< XSDDataType > XSDValidationHelper::getValidatingDataType( ) const SAL_THROW(()) 192 { 193 return getDataTypeByName( getValidatingDataTypeName() ); 194 } 195 196 //-------------------------------------------------------------------- 197 bool XSDValidationHelper::cloneDataType( const ::rtl::Reference< XSDDataType >& _pDataType, const ::rtl::OUString& _rNewName ) const SAL_THROW(()) 198 { 199 OSL_ENSURE( _pDataType.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type!" ); 200 if ( !_pDataType.is() ) 201 return false; 202 203 try 204 { 205 Reference< XDataTypeRepository > xRepository( getDataTypeRepository() ); 206 OSL_ENSURE( xRepository.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type repository!" ); 207 if ( !xRepository.is() ) 208 return false; 209 210 Reference< XDataType > xDataType( _pDataType->getUnoDataType() ); 211 OSL_ENSURE( xDataType.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type (II)!" ); 212 if ( !xDataType.is() ) 213 return false; 214 215 xRepository->cloneDataType( xDataType->getName(), _rNewName ); 216 } 217 catch( const Exception& ) 218 { 219 OSL_ENSURE( sal_False, "XSDValidationHelper::cloneDataType: caught an exception!" ); 220 } 221 return true; 222 } 223 224 //-------------------------------------------------------------------- 225 bool XSDValidationHelper::removeDataTypeFromRepository( const ::rtl::OUString& _rName ) const SAL_THROW(()) 226 { 227 try 228 { 229 Reference< XDataTypeRepository > xRepository( getDataTypeRepository() ); 230 OSL_ENSURE( xRepository.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type repository!" ); 231 if ( !xRepository.is() ) 232 return false; 233 234 if ( !xRepository->hasByName( _rName ) ) 235 { 236 OSL_ENSURE( sal_False, "XSDValidationHelper::removeDataTypeFromRepository: invalid repository and/or data type!" ); 237 return false; 238 } 239 240 xRepository->revokeDataType( _rName ); 241 } 242 catch( const Exception& ) 243 { 244 OSL_ENSURE( sal_False, "XSDValidationHelper::removeDataTypeFromRepository: caught an exception!" ); 245 return false; 246 } 247 return true; 248 } 249 250 //-------------------------------------------------------------------- 251 void XSDValidationHelper::setValidatingDataTypeByName( const ::rtl::OUString& _rName ) const SAL_THROW(()) 252 { 253 try 254 { 255 Reference< XPropertySet > xBinding( getCurrentBinding() ); 256 OSL_ENSURE( xBinding.is(), "XSDValidationHelper::setValidatingDataTypeByName: no active binding - how this?" ); 257 258 if ( xBinding.is() ) 259 { 260 // get the old data type - this is necessary for notifying property changes 261 ::rtl::OUString sOldDataTypeName; 262 OSL_VERIFY( xBinding->getPropertyValue( PROPERTY_XSD_DATA_TYPE ) >>= sOldDataTypeName ); 263 Reference< XPropertySet > xOldType; 264 try { xOldType = xOldType.query( getDataType( sOldDataTypeName ) ); } catch( const Exception& ) { } 265 266 // set the new data type name 267 xBinding->setPropertyValue( PROPERTY_XSD_DATA_TYPE, makeAny( _rName ) ); 268 269 // retrieve the new data type object 270 Reference< XPropertySet > xNewType( getDataType( _rName ), UNO_QUERY ); 271 272 // fire any changes in the properties which result from this new type 273 std::set< ::rtl::OUString > aFilter; aFilter.insert( PROPERTY_NAME ); 274 firePropertyChanges( xOldType, xNewType, aFilter ); 275 276 // fire the change in the Data Type property 277 ::rtl::OUString sNewDataTypeName; 278 OSL_VERIFY( xBinding->getPropertyValue( PROPERTY_XSD_DATA_TYPE ) >>= sNewDataTypeName ); 279 firePropertyChange( PROPERTY_XSD_DATA_TYPE, makeAny( sOldDataTypeName ), makeAny( sNewDataTypeName ) ); 280 } 281 } 282 catch( const Exception& ) 283 { 284 DBG_UNHANDLED_EXCEPTION(); 285 } 286 } 287 288 //-------------------------------------------------------------------- 289 void XSDValidationHelper::copyDataType( const ::rtl::OUString& _rFromModel, const ::rtl::OUString& _rToModel, 290 const ::rtl::OUString& _rDataTypeName ) const SAL_THROW(()) 291 { 292 if ( _rFromModel == _rToModel ) 293 // nothing to do (me thinks) 294 return; 295 296 try 297 { 298 Reference< XDataTypeRepository > xFromRepository, xToRepository; 299 if ( _rFromModel.getLength() ) 300 xFromRepository = getDataTypeRepository( _rFromModel ); 301 if ( _rToModel.getLength() ) 302 xToRepository = getDataTypeRepository( _rToModel ); 303 304 if ( !xFromRepository.is() || !xToRepository.is() ) 305 return; 306 307 if ( !xFromRepository->hasByName( _rDataTypeName ) || xToRepository->hasByName( _rDataTypeName ) ) 308 // not existent in the source, or already existent (by name) in the destination 309 return; 310 311 // determine the built-in type belonging to the source type 312 ::rtl::Reference< XSDDataType > pSourceType = new XSDDataType( xFromRepository->getDataType( _rDataTypeName ) ); 313 ::rtl::OUString sTargetBaseType = getBasicTypeNameForClass( pSourceType->classify(), xToRepository ); 314 315 // create the target type 316 Reference< XDataType > xTargetType = xToRepository->cloneDataType( sTargetBaseType, _rDataTypeName ); 317 ::rtl::Reference< XSDDataType > pTargetType = new XSDDataType( xTargetType ); 318 319 // copy the facets 320 pTargetType->copyFacetsFrom( pSourceType ); 321 } 322 catch( const Exception& ) 323 { 324 OSL_ENSURE( sal_False, "XSDValidationHelper::copyDataType: caught an exception!" ); 325 } 326 } 327 328 //-------------------------------------------------------------------- 329 void XSDValidationHelper::findDefaultFormatForIntrospectee() SAL_THROW(()) 330 { 331 try 332 { 333 ::rtl::Reference< XSDDataType > xDataType = getValidatingDataType(); 334 if ( xDataType.is() ) 335 { 336 // find a NumberFormat type corresponding to the DataTypeClass 337 sal_Int16 nNumberFormatType = NumberFormat::NUMBER; 338 switch ( xDataType->classify() ) 339 { 340 case DataTypeClass::DATETIME: 341 nNumberFormatType = NumberFormat::DATETIME; 342 break; 343 case DataTypeClass::DATE: 344 nNumberFormatType = NumberFormat::DATE; 345 break; 346 case DataTypeClass::TIME: 347 nNumberFormatType = NumberFormat::TIME; 348 break; 349 case DataTypeClass::STRING: 350 case DataTypeClass::anyURI: 351 case DataTypeClass::QName: 352 case DataTypeClass::NOTATION: 353 nNumberFormatType = NumberFormat::TEXT; 354 break; 355 } 356 357 // get the number formatter from the introspectee 358 Reference< XNumberFormatsSupplier > xSupplier; 359 Reference< XNumberFormatTypes > xFormatTypes; 360 OSL_VERIFY( m_xControlModel->getPropertyValue( PROPERTY_FORMATSSUPPLIER ) >>= xSupplier ); 361 if ( xSupplier.is() ) 362 xFormatTypes = xFormatTypes.query( xSupplier->getNumberFormats() ); 363 OSL_ENSURE( xFormatTypes.is(), "XSDValidationHelper::findDefaultFormatForIntrospectee: no number formats for the introspectee!" ); 364 if ( !xFormatTypes.is() ) 365 return; 366 367 // and the standard format for the given NumberFormat type 368 sal_Int32 nDesiredFormat = xFormatTypes->getStandardFormat( nNumberFormatType, SvtSysLocale().GetLocaleData().getLocale() ); 369 370 // set this at the introspectee 371 m_xControlModel->setPropertyValue( PROPERTY_FORMATKEY, makeAny( nDesiredFormat ) ); 372 } 373 } 374 catch( const Exception& ) 375 { 376 OSL_ENSURE( sal_False, "XSDValidationHelper::findDefaultFormatForIntrospectee: caught an exception!" ); 377 } 378 } 379 380 //-------------------------------------------------------------------- 381 ::rtl::OUString XSDValidationHelper::getBasicTypeNameForClass( sal_Int16 _nClass ) const SAL_THROW(()) 382 { 383 return getBasicTypeNameForClass( _nClass, getDataTypeRepository() ); 384 } 385 386 //-------------------------------------------------------------------- 387 ::rtl::OUString XSDValidationHelper::getBasicTypeNameForClass( sal_Int16 _nClass, Reference< XDataTypeRepository > _rxRepository ) const SAL_THROW(()) 388 { 389 ::rtl::OUString sReturn; 390 OSL_ENSURE( _rxRepository.is(), "XSDValidationHelper::getBasicTypeNameForClass: invalid repository!" ); 391 if ( !_rxRepository.is() ) 392 return sReturn; 393 394 try 395 { 396 Reference< XDataType > xDataType = _rxRepository->getBasicDataType( _nClass ); 397 OSL_ENSURE( xDataType.is(), "XSDValidationHelper::getBasicTypeNameForClass: invalid data type returned!" ); 398 if ( xDataType.is() ) 399 sReturn = xDataType->getName(); 400 } 401 catch( const Exception& ) 402 { 403 OSL_ENSURE( sal_False, "XSDValidationHelper::getBasicTypeNameForClass: caught an exception!" ); 404 } 405 406 return sReturn; 407 } 408 409 //........................................................................ 410 } // namespace pcr 411 //........................................................................ 412 413