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