LibreOffice Module extensions (master) 1
xsdvalidationhelper.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
21#include "xsddatatypes.hxx"
22#include "formstrings.hxx"
23
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>
33
34
35namespace pcr
36{
37
38
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;
46
47 namespace NumberFormat = ::com::sun::star::util::NumberFormat;
48
49
50 //= XSDValidationHelper
51
52
53 XSDValidationHelper::XSDValidationHelper( ::osl::Mutex& _rMutex, const Reference< XPropertySet >& _rxIntrospectee, const Reference< frame::XModel >& _rxContextDocument )
54 :EFormsHelper( _rMutex, _rxIntrospectee, _rxContextDocument )
55 ,m_bInspectingFormattedField( false )
56 {
57 try
58 {
59 Reference< XPropertySetInfo > xPSI;
60 Reference< XServiceInfo > xSI( _rxIntrospectee, UNO_QUERY );
61 if ( m_xControlModel.is() )
62 xPSI = m_xControlModel->getPropertySetInfo();
63 if ( xPSI.is()
64 && xPSI->hasPropertyByName( PROPERTY_FORMATKEY )
65 && xPSI->hasPropertyByName( PROPERTY_FORMATSSUPPLIER )
66 && xSI.is()
67 && xSI->supportsService( SERVICE_COMPONENT_FORMATTEDFIELD )
68 )
70 }
71 catch( const Exception& )
72 {
73 TOOLS_WARN_EXCEPTION("extensions.propctrlr",
74 "caught an exception while examining the introspectee!");
75 }
76 }
77
78
79 void XSDValidationHelper::getAvailableDataTypeNames( std::vector< OUString >& /* [out] */ _rNames ) const
80 {
81 _rNames.resize( 0 );
82
83 try
84 {
85 Reference< XDataTypeRepository > xRepository = getDataTypeRepository();
86 if ( xRepository.is() )
87 {
88 const Sequence<OUString> aElements = xRepository->getElementNames();
89
90 _rNames.resize( aElements.getLength() );
91 std::copy( aElements.begin(), aElements.end(), _rNames.begin() );
92 }
93 }
94 catch( const Exception& )
95 {
96 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::getAvailableDataTypeNames" );
97 }
98 }
99
100
101 Reference< XDataTypeRepository > XSDValidationHelper::getDataTypeRepository() const
102 {
103 Reference< XDataTypeRepository > xRepository;
104
105 Reference< xforms::XModel > xModel( getCurrentFormModel( ) );
106 if ( xModel.is() )
107 xRepository = xModel->getDataTypeRepository();
108
109 return xRepository;
110 }
111
112
113 Reference< XDataTypeRepository > XSDValidationHelper::getDataTypeRepository( const OUString& _rModelName ) const
114 {
115 Reference< XDataTypeRepository > xRepository;
116
117 Reference< xforms::XModel > xModel( getFormModelByName( _rModelName ) );
118 if ( xModel.is() )
119 xRepository = xModel->getDataTypeRepository();
120
121 return xRepository;
122 }
123
124
125 Reference< XDataType > XSDValidationHelper::getDataType( const OUString& _rName ) const
126 {
127 Reference< XDataType > xDataType;
128
129 if ( !_rName.isEmpty() )
130 {
131 Reference< XDataTypeRepository > xRepository = getDataTypeRepository();
132 if ( xRepository.is() )
133 xDataType = xRepository->getDataType( _rName );
134 }
135 return xDataType;
136 }
137
138
140 {
141 OUString sDataTypeName;
142 try
143 {
144 Reference< XPropertySet > xBinding( getCurrentBinding() );
145 // it's allowed here to not (yet) have a binding
146 if ( xBinding.is() )
147 {
148 OSL_VERIFY( xBinding->getPropertyValue( PROPERTY_XSD_DATA_TYPE ) >>= sDataTypeName );
149 }
150 }
151 catch( const Exception& )
152 {
153 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::getValidatingDataTypeName" );
154 }
155 return sDataTypeName;
156 }
157
158
160 {
162
163 try
164 {
165 Reference< XDataType > xValidatedAgainst;
166
167 if ( !_rName.isEmpty() )
168 xValidatedAgainst = getDataType( _rName );
169
170 if ( xValidatedAgainst.is() )
171 pReturn = new XSDDataType( xValidatedAgainst );
172 }
173 catch( const Exception& )
174 {
175 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::getDataTypeByName" );
176 }
177
178 return pReturn;
179 }
180
181
183 {
185 }
186
187
188 bool XSDValidationHelper::cloneDataType( const ::rtl::Reference< XSDDataType >& _pDataType, const OUString& _rNewName ) const
189 {
190 OSL_ENSURE( _pDataType.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type!" );
191 if ( !_pDataType.is() )
192 return false;
193
194 try
195 {
196 Reference< XDataTypeRepository > xRepository( getDataTypeRepository() );
197 OSL_ENSURE( xRepository.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type repository!" );
198 if ( !xRepository.is() )
199 return false;
200
201 Reference< XDataType > xDataType( _pDataType->getUnoDataType() );
202 OSL_ENSURE( xDataType.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type (II)!" );
203 if ( !xDataType.is() )
204 return false;
205
206 xRepository->cloneDataType( xDataType->getName(), _rNewName );
207 }
208 catch( const Exception& )
209 {
210 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::cloneDataType" );
211 }
212 return true;
213 }
214
215
216 bool XSDValidationHelper::removeDataTypeFromRepository( const OUString& _rName ) const
217 {
218 try
219 {
220 Reference< XDataTypeRepository > xRepository( getDataTypeRepository() );
221 OSL_ENSURE( xRepository.is(), "XSDValidationHelper::removeDataTypeFromRepository: invalid data type repository!" );
222 if ( !xRepository.is() )
223 return false;
224
225 if ( !xRepository->hasByName( _rName ) )
226 {
227 OSL_FAIL( "XSDValidationHelper::removeDataTypeFromRepository: invalid repository and/or data type!" );
228 return false;
229 }
230
231 xRepository->revokeDataType( _rName );
232 }
233 catch( const Exception& )
234 {
235 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::removeDataTypeFromRepository" );
236 return false;
237 }
238 return true;
239 }
240
241
242 void XSDValidationHelper::setValidatingDataTypeByName( const OUString& _rName ) const
243 {
244 try
245 {
246 Reference< XPropertySet > xBinding( getCurrentBinding() );
247 OSL_ENSURE( xBinding.is(), "XSDValidationHelper::setValidatingDataTypeByName: no active binding - how this?" );
248
249 if ( xBinding.is() )
250 {
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;
255 try {
256 xOldType = getDataType( sOldDataTypeName );
257 } catch( const Exception& ) { }
258
259 // set the new data type name
260 xBinding->setPropertyValue( PROPERTY_XSD_DATA_TYPE, Any( _rName ) );
261
262 // retrieve the new data type object
263 Reference< XPropertySet > xNewType = getDataType( _rName );
264
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 );
268
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 ) );
273 }
274 }
275 catch( const Exception& )
276 {
277 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
278 }
279 }
280
281
282 void XSDValidationHelper::copyDataType( const OUString& _rFromModel, const OUString& _rToModel,
283 const OUString& _rDataTypeName ) const
284 {
285 if ( _rFromModel == _rToModel )
286 // nothing to do (me thinks)
287 return;
288
289 try
290 {
291 Reference< XDataTypeRepository > xFromRepository, xToRepository;
292 if ( !_rFromModel.isEmpty() )
293 xFromRepository = getDataTypeRepository( _rFromModel );
294 if ( !_rToModel.isEmpty() )
295 xToRepository = getDataTypeRepository( _rToModel );
296
297 if ( !xFromRepository.is() || !xToRepository.is() )
298 return;
299
300 if ( !xFromRepository->hasByName( _rDataTypeName ) || xToRepository->hasByName( _rDataTypeName ) )
301 // not existent in the source, or already existent (by name) in the destination
302 return;
303
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 );
307
308 // create the target type
309 Reference< XDataType > xTargetType = xToRepository->cloneDataType( sTargetBaseType, _rDataTypeName );
310 ::rtl::Reference< XSDDataType > pTargetType = new XSDDataType( xTargetType );
311
312 // copy the facets
313 pTargetType->copyFacetsFrom( pSourceType );
314 }
315 catch( const Exception& )
316 {
317 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::copyDataType" );
318 }
319 }
320
321
323 {
324 try
325 {
327 if ( xDataType.is() )
328 {
329 // find a NumberFormat type corresponding to the DataTypeClass
330 sal_Int16 nNumberFormatType = NumberFormat::NUMBER;
331 switch ( xDataType->classify() )
332 {
333 case DataTypeClass::DATETIME:
334 nNumberFormatType = NumberFormat::DATETIME;
335 break;
336 case DataTypeClass::DATE:
337 nNumberFormatType = NumberFormat::DATE;
338 break;
339 case DataTypeClass::TIME:
340 nNumberFormatType = NumberFormat::TIME;
341 break;
342 case DataTypeClass::STRING:
343 case DataTypeClass::anyURI:
344 case DataTypeClass::QName:
345 case DataTypeClass::NOTATION:
346 nNumberFormatType = NumberFormat::TEXT;
347 break;
348 }
349
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() )
358 return;
359
360 // and the standard format for the given NumberFormat type
361 sal_Int32 nDesiredFormat = xFormatTypes->getStandardFormat( nNumberFormatType, SvtSysLocale().GetLanguageTag().getLocale() );
362
363 // set this at the introspectee
364 m_xControlModel->setPropertyValue( PROPERTY_FORMATKEY, Any( nDesiredFormat ) );
365 }
366 }
367 catch( const Exception& )
368 {
369 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::findDefaultFormatForIntrospectee" );
370 }
371 }
372
373
374 OUString XSDValidationHelper::getBasicTypeNameForClass( sal_Int16 _nClass ) const
375 {
377 }
378
379
380 OUString XSDValidationHelper::getBasicTypeNameForClass( sal_Int16 _nClass, const Reference< XDataTypeRepository >& _rxRepository )
381 {
382 OUString sReturn;
383 OSL_ENSURE( _rxRepository.is(), "XSDValidationHelper::getBasicTypeNameForClass: invalid repository!" );
384 if ( !_rxRepository.is() )
385 return sReturn;
386
387 try
388 {
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();
393 }
394 catch( const Exception& )
395 {
396 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "XSDValidationHelper::getBasicTypeNameForClass" );
397 }
398
399 return sReturn;
400 }
401
402
403} // namespace pcr
404
405
406/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::beans::XPropertySet > m_xControlModel
void firePropertyChange(const OUString &_rName, const css::uno::Any &_rOldValue, const css::uno::Any &_rNewValue) const
fires a change in a single property, if the property value changed, and if we have a listener interes...
css::uno::Reference< css::xforms::XModel > getCurrentFormModel() const
retrieves the model which the active binding of the control model belongs to
css::uno::Reference< css::xforms::XModel > getFormModelByName(const OUString &_rModelName) const
retrieves the XForms model (within the control model's document) with the given name
css::uno::Reference< css::beans::XPropertySet > getCurrentBinding() const
retrieves the binding instance which is currently attached to the control model
void firePropertyChanges(const css::uno::Reference< css::beans::XPropertySet > &_rxOldProps, const css::uno::Reference< css::beans::XPropertySet > &_rxNewProps, std::set< OUString > &_rFilter) const
css::uno::Reference< css::xsd::XDataType > getDataType(const OUString &_rName) const
retrieves the data type object for the given name
::rtl::Reference< XSDDataType > getDataTypeByName(const OUString &_rName) const
retrieves a particular data type given by name
void findDefaultFormatForIntrospectee()
finds (and sets) a default format for the formatted field we're inspecting, according to the current ...
void setValidatingDataTypeByName(const OUString &_rName) const
binds the validator to a new data type
OUString getValidatingDataTypeName() const
retrieves the name of the data type which the control model is currently validated against
css::uno::Reference< css::xforms::XDataTypeRepository > getDataTypeRepository() const
retrieves the data type repository associated with the current model
bool removeDataTypeFromRepository(const OUString &_rName) const
removes the data type given by name from the data type repository
XSDValidationHelper(::osl::Mutex &_rMutex, const css::uno::Reference< css::beans::XPropertySet > &_rxIntrospectee, const css::uno::Reference< css::frame::XModel > &_rxContextDocument)
::rtl::Reference< XSDDataType > getValidatingDataType() const
retrieves the DataType instance which the control model is currently validated against
bool cloneDataType(const ::rtl::Reference< XSDDataType > &_pDataType, const OUString &_rNewName) const
creates a new data type, which is a clone of an existing data type
void getAvailableDataTypeNames(std::vector< OUString > &_rNames) const
retrieves the names of all XForms models in the document the control lives in
void copyDataType(const OUString &_rFromModel, const OUString &_rToModel, const OUString &_rDataTypeName) const
copy a data type from one model to another
OUString getBasicTypeNameForClass(sal_Int16 _eClass) const
retrieves the name of the basic data type which has the given class
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
constexpr OUStringLiteral PROPERTY_NAME
Definition: formstrings.hxx:36
constexpr OUStringLiteral SERVICE_COMPONENT_FORMATTEDFIELD
constexpr OUStringLiteral PROPERTY_XSD_DATA_TYPE
constexpr OUStringLiteral PROPERTY_FORMATKEY
Definition: formstrings.hxx:64
constexpr OUStringLiteral PROPERTY_FORMATSSUPPLIER
Definition: formstrings.hxx:65
@ Exception
const LanguageTag & getLocale()
a property handler for any virtual string properties
Definition: browserline.cxx:39
Reference< XModel > xModel